文章目錄
一、volatile的應用
volatile是輕量級的synchronized,在多線程中保證了共享變量的"可見性"。如果volatile變量修飾符使用恰當的話,它比synchronized的使用和執行成本更低,因爲它不會引起線程上下文的切換和調度;
volatile的定義與實現原理
volatile修飾的共享變量,在多核處理器下會引發兩件事情:
- 將當前處理器緩存航的數據寫會到系統內存
- 這個寫回內存的操作會使在其他CPU裏緩存了該內存地址的數據無效
爲了提高處理速度,處理器不直接和內存進行通信,而是先將系統內存的數據讀到緩存後再進行操作,但操作完不知道何時會寫到內存。如果對聲明瞭volatile的變量進行寫操作,JVM就會向處理器發送一條Lock前綴的指令,將這個變量所在緩存行的數據寫回到系統內存。同時其他處理器會將緩存中該變量的數據置爲無效(緩存一致性協議),從內存中重新讀取;
volatile的使用優化
舉例:
隊列集合:LinkedTransferQueue 使用追加字節的方式優化隊列的出隊和入隊性能;
並不是所有的使用volatile的變量都應該追加到64個字節:
追加字節,與處理器的緩存行處理字節數相關,有些處理器的緩存行是32個字節寬,就沒有必要增加字節;
如果共享變量不會被頻繁的寫,鎖機率非常小,也沒有必要通過追加字節的方式來避免相互鎖定;
二、Synchronized的實現原理和應用
synchronized實現同步的基礎,Java中的每一個對象都可以作爲鎖,具體表現爲下面三種形式:
- 對於普通同步方法,鎖時當前實力對象
- 對於靜態同步方法,鎖時當前類的Class對象
- 對於同步方法塊,鎖時Synchronized括號裏配置的對象
Java對象頭
synchronized用的鎖是存儲在對象頭中的;如果對象是數組類型,則虛擬機用3個字節寬存儲對象頭,如果對象是非數組類型,則用2個字節寬存儲對象頭;
鎖的升級與對比
JavaSE1.6爲了減少獲得鎖和釋放鎖帶來的性能消耗,引入了"偏向鎖"和"輕量級鎖";在JavaSE1.6中,鎖一共有4種狀態,級別從低到高依次是:無鎖狀態、偏向鎖、輕量級鎖、重量級鎖,這幾個狀態會隨着競爭情況逐漸升級;
鎖可以升級,但不能降級,目的是爲了提高獲得鎖和釋放鎖的效率;
鎖的優缺點與對比
鎖 | 優點 | 缺點 | 適用場景 |
---|---|---|---|
偏向鎖 | 加鎖和解鎖不需要額外的消耗,和執行非同步方法相比僅存在納秒級的差距 | 如果線程間存在鎖競爭,會帶來額外的鎖撤銷的消耗 | 適用於只有一個線程訪問同步塊場景 |
輕量級鎖 | 競爭的線程不會阻塞,提高了程序的響應速度 | 如果始終得不到鎖競爭的線程,使用自旋會消耗CPU | 追求響應時間,同步塊執行速度非常快 |
重量級鎖 | 線程競爭不適用自旋,不會消耗CPU | 線程阻塞,響應時間慢 | 追求吞吐量,同步塊響應時間長 |
Java如何實現原子操作
-
使用CAS實現原子操作
JDK併發包裏提供了一些使用CAS支持原子操作的類,如:AtomicBoolean,AtomicInteger,AtomicLong,同時提供了有用的工具方法,比如自增、自減; -
使用鎖機制實現原子操作