多线程:线程同步的几种方式
1.synchronized同步方法?(靜態方法鎖住類對象,其它方法鎖住實例對象)
????即有synchronized關鍵字修飾的方法。?
????由于java的每個對象都有一個內置鎖,當用此關鍵字修飾方法時,?
????內置鎖會保護整個方法。在調用該方法前,需要獲得內置鎖,否則就處于阻塞狀態。
?
2.synchronized同步代碼塊?(鎖住標記的對象)
????即有synchronized關鍵字修飾的語句塊。?
????被該關鍵字修飾的語句塊會自動被加上內置鎖,從而實現同步?
?
3.使用ReentrantLock實現線程同步
在JavaSE5.0中新增了一個java.util.concurrent包來支持同步。ReentrantLock類是可重入、互斥、實現了Lock接口的鎖,?它與使用synchronized方法和快具有相同的基本行為和語義,并且擴展了其能力。
?????ReenreantLock類的常用方法有:
?????????ReentrantLock() : 創建一個ReentrantLock實例?
?????????lock() : 獲得鎖?
代碼
?????????unlock() : 釋放鎖?
????注:ReentrantLock()還有一個可以創建公平鎖的構造方法,但由于能大幅度降低程序運行效率,不推薦使用?
用于線程間通信時,結合Condition進行操作
?
4.使用特殊域變量(volatile)實現線程同步(無法保證原子性的,寫到這兒來只是強調一下,它只保證了可見性和有序性。)
????a.volatile關鍵字為域變量的訪問提供了一種免鎖機制,?
????b.使用volatile修飾域相當于告訴虛擬機該域可能會被其他線程更新,?
????c.因此每次使用該域就要重新計算,而不是使用寄存器中的值?
d.volatile不會提供任何原子操作,它也不能用來修飾final類型的變量?
e.
對于volatile修飾的變量,jvm虛擬機只是保證從主內存加載到線程工作內存的值是最新的。
您只能在有限的一些情形下使用 volatile 變量替代鎖。要使 volatile 變量提供理想的線程安全,必須同時滿足下面兩個條件:
·??對變量的寫操作不依賴于當前值。
·??該變量沒有包含在具有其他變量的不變式中。
可以使用的場景:
將volatile 變量作為狀態標志使用(和lock差不多,但是volatile賦值true本來這種就是原子操作,所以就剛好可以使用。)
?
5.volatile(保證可見性和有序性)的一個重要作用就是和CAS結合,保證了原子性
??????最簡單的比如i++,用volatile可以保證取得的值是最新的,而cas操作可以保證你修改前后的值只+1,而不會覆蓋掉別的線程已經修改過的值,如果別的線程已經修改過,CAS會自動不修改的。
??????但是沒有volatile時,原子性不保證可見性。
???????CAS改完可能值還在緩存里,不會馬上把工作內存中被修改后的值 寫回 主內存。
CAS只解決了比較和更新的原子性的問題,要保證可見性,需要加鎖或者是用volatile修飾變量。
1.??????首先,聲明共享變量為volatile;
2.??????然后,使用CAS的原子條件更新來實現線程之間的同步;
3.??????同時,配合以volatile的讀/寫和CAS所具有的volatile讀和寫的內存語義來實現線程之間的通信。
一句話:volatile變量的讀/寫和CAS可以實現線程之間的通信。把這些特性整合在一起,就形成了整個concurrent包得以實現的基石。
?
總結
以上是生活随笔為你收集整理的多线程:线程同步的几种方式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 多线程:线程池
- 下一篇: 多线程:线程池里的队列BlockingQ