并发基础知识 — 线程安全性
前段時間看完了《并發(fā)編程的藝術(shù)》,總感覺自己對于并發(fā)缺少一些整體的認識。今天借助《Java并發(fā)編程實踐》,從一些基本概念開始,重新整理一下自己學(xué)過并發(fā)編程。從并發(fā)基礎(chǔ)開始,深入進去,系統(tǒng)學(xué)習(xí)一下并發(fā)編程。
編寫線程安全的代碼,核心在于要對狀態(tài)訪問操作進行管理,特別是對共享的(Shared)和可變的(Mutable)狀態(tài)的訪問。對象的狀態(tài)是指存儲在狀態(tài)變量(實例或靜態(tài)域)中的數(shù)據(jù)。對象的狀態(tài)還可能包括其他依賴對象的域。(Map.Entry)
一個對象是否需要時線程安全的,取決于該對象是否被多線程訪問。這指的是程序中訪問對象的方式,而不是對象要實現(xiàn)的功能。要使得對象是線程安全的,要采用同步機制來協(xié)同對對象可變狀態(tài)的訪問。Java常用的同步機制是Synchronized,還包括?volatile類型的變量,顯示鎖以及原子變量。
線程安全的程序是否完全由線程安全的類構(gòu)成?答案是否定的,完全由線程安全的類構(gòu)成的程序并不一定是線程安全的,線程安全類中也可以包含非線程安全的類。只有當類中僅包含自己的狀態(tài)時,線程安全類才有意義!
什么是線程安全性?
當多個線程訪問某個類時,不管運行時環(huán)境采用何種調(diào)度方式或者這些線程將如何交替執(zhí)行,并且在主調(diào)代碼中不需要任何額外的同步或協(xié)同,這個類都能表現(xiàn)出正確的行為,那么這個類就是線程安全的。
正確性:某個類的行為與其規(guī)范相一致。(我理解的規(guī)范就是我們在編寫類時,能預(yù)知的狀態(tài)結(jié)果)
原子性
競態(tài)條件(Race Condition):某個計算的正確性取決于多個線程的交替執(zhí)行的時序。(線程的時序不同,產(chǎn)生的結(jié)果可能會不同)
“先檢查后執(zhí)行”,即通過一個可能失效的觀測結(jié)果來決定下一步的操作。
首先觀察到某個條件為真,然后開始執(zhí)行相關(guān)的程序,但是在多線程的運行環(huán)境中,條件判斷的結(jié)果以及開始執(zhí)行程序中間,觀察結(jié)果可能變得無效(另外一個線程在此期間執(zhí)行了相關(guān)的動作),從而導(dǎo)致無效。常見的就是(Lazy Singleton)
LazySingleton“讀取-修改-寫入”,基于對象之前的狀態(tài)來定義對象狀態(tài)的轉(zhuǎn)換。即使是volatile修飾的變量,在多線程的環(huán)境里面進行自增操作,同樣會發(fā)生競態(tài)條件,所以volatile不能保證絕對的線程安全(360面試問題)。
引用書中定義:假定有兩個操作A和B,如果從執(zhí)行A的線程來看,當另一個線程執(zhí)行B時,要么將B完全執(zhí)行完,要么完全不執(zhí)行B,那么A和B對彼此來說是原子的。原子操作是指:對于訪問同一個狀態(tài)的所有操作(包括該操作本身)來說,這個操作是一個以原子方式執(zhí)行的操作。
加鎖機制
在線程安全的定義中,多個線程間的操作無論采用何種執(zhí)行時序或交替方式,都要保證不變性條件不被破壞。當不變性條件中涉及多個變量時,各個變量之間并不是互相獨立的,一個變量發(fā)生變化會對其他變量的值產(chǎn)生約束。因此,一個變量發(fā)生改變,在同一個原子操作里面,其他相關(guān)變量也要更新。
內(nèi)置鎖:同步代碼塊(Synchronized Block)包括兩部分:一個作為鎖的對象引用,一個作為由這個鎖保護的代碼塊。關(guān)鍵字Synchronized修飾方法就是一種同步代碼塊,鎖就是方法調(diào)用所在的對象,靜態(tài)的Synchronized方法以Class對象作為鎖。內(nèi)置鎖或監(jiān)視鎖就是以對象作為實現(xiàn)同步的鎖。
Java內(nèi)置鎖,進入的唯一途徑是執(zhí)行進入由鎖保護的同步代碼塊或方法。它相當于一種互斥鎖。
重入鎖:當一個持有鎖的線程再次請求進入自己持有的鎖時,該請求會成功。"重入"意味著獲取鎖的操作的粒度是“線程”,而不是“調(diào)用”。重入的一種實現(xiàn)方式,為每個鎖關(guān)聯(lián)一個計數(shù)器和線程持有者。
用鎖來保護狀態(tài)
由于鎖能使其保護的代碼路徑以串行形式訪問,因此可以通過鎖來構(gòu)造一些協(xié)議以實現(xiàn)對共享狀態(tài)的獨占訪問。
對象的內(nèi)置鎖與其狀態(tài)之間沒有內(nèi)在的聯(lián)系,雖然大多數(shù)類都將內(nèi)置鎖用做一種有效的加鎖機制,但對象的域并不一定要通過內(nèi)置鎖來保護。
對于每個包含多個變量的不變性條件,其中涉及的所有變量都要使用同一個鎖來保護/同步。
https://www.cnblogs.com/tcming/p/6711506.html
總結(jié)
以上是生活随笔為你收集整理的并发基础知识 — 线程安全性的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 支付宝网商银行有什么用
- 下一篇: Jquery DataTable基本使用