java併發編程實戰(java concurrency in practice)

第一章
 
線程共享進程範圍內的資源,但每一個線程都有各自的程序計數器、棧以及局部變量等。
多個線程能夠同時調度到多個CPU上運行。
 
線程的優點?
在服務應用程序中,能夠提高資源利用率以及系統吞吐率,發揮多處理器的強大功能。
 
線程的優先級  執行時間  線程切換須要額外的開銷
 
第二章
 
若是多個線程訪問同一個可變的狀態變量是沒有使用合適的同步,那麼程序就會出現錯誤,有如下三種方法修復這種問題。
一、不在線程之間共享該狀態變量
二、將狀態變量改成不可變的變量
三、在訪問狀態變量時使用同步
 
什麼是線程安全?本身百度
 
無狀態對象必定是線程安全的
 
注意count++這類操做的問題:不是原子的,其實是三部操做 讀取-修改-寫入
 
什麼是競態條件?
在併發編程中,因爲不恰當的執行時序從而使得結果變得不可靠。常見的競態條件類型就是「先檢查後執行」 ,例如常見的對象懶加載
 
一個包:java.concurrent.atomic
 
 
內置鎖:加鎖機制,java中用於確保原子性的內置機制。同步代碼塊、同步方法
以synchronized來修飾的方法叫同步方法,該同步代碼塊的鎖就是方法調用所在的對象,靜態的 synchronized方法以Class對象做爲鎖
 
每一個java對象均可以用做實現一個同步的鎖,稱爲內置鎖或監視器鎖。
線程在進入同步代碼塊前會自動得到鎖,而且在退出同步代碼塊時自動釋放鎖。
 
內置鎖是可重入的。
 
理解一句話:狀態變量是由這個鎖保護的。
 
鎖不要濫用,同步代碼塊太大會引發不良併發,大大拉低程序性能。當執行較長的計算或者可能沒法快速完成的操做時(如網絡I/O、控制檯I/O),必定不要持有鎖。
 
第三章
 
同步機制不僅是爲了實現原子性或者肯定「臨界區」,還確保了多個線程之間對內存操做的可見性。
加鎖的含義不只僅侷限於互斥行爲,還包含內存可見性。
 
注意重排序現象
 
最低安全性:當線程在沒有進行同步的狀況下讀取變量時,可能會的到一個時效值,但至少這個值是由以前某個線程設置的,而不是一個隨機值。
非volatile類型的64位數值變量(double和long)不適用於最低安全性,由於JVM容許將64位的讀操做或寫操做分解爲兩個32位的操做
 
一種稍弱的同步機制,即volatile變量。
加鎖機制便可以確保可見性又能夠確保原子性,而volatile變量只能確保可見性。(確保只有單個線程更新變量的值時能夠用 volatile變量 )
 
發佈一個對象
意思是指,是對象可以在當前做用域以外的代碼中使用。
 
逸出
當某個不該該發佈的對象被髮布時,被稱爲逸出。
 
發佈對象的方式:
發佈對象最簡單的方法是將對象的引用保存到一個公有的靜態變量中。
從非私有的方法中返回一個對象的引用,如java web開發中經常使用的get set方法。
發佈一個內部類的實例(內部類實例包含外部類實例的引用)
 
不要在構造過程當中使用this引用逸出(只有在構造函數返回時,this引用才應該從線程中逸出)
 
線程封閉
若是在單線程內訪問數據,就不須要同步。這種技術稱爲線程封閉。
 
實現線程封閉的方法:
Ad-hoc線程封閉(瞭解)
棧封閉(在方法內的局部變量訪問對象,熟悉)
ThreadLocal類(經常使用)
 
ThreadLocal類
這個類能使線程中的某個值與保存值的對象關聯起來。該類提供get與set等訪問接口或方法,這些方法爲每一個使用該變量的線程都存有一份獨立副本,所以get老是返回當前線程在調用set時設置的最新值。當線程終止後,這些值會做爲垃圾回收。
 
不可變對象必定是線程安全的
 
知足如下條件時,對象纔是不可變的:
對象建立之後其狀態就不能夠修改
對象的全部域都是final類型
對象是正確建立的(建立對象時,this引用沒有逸出)
相關文章
相關標籤/搜索