線程可見性


1.可見性
一個線程對共享變量值得修改,能夠及時的被其他線程看到。

2.共享變量
如果一個變量在多個線程的工作內存中都存在副本,那么這個變量就是這幾個線程的共享變量。

3.Java內存模型
描述了Java程序中各種變量(線程共享變量)的訪問規則,以及在jvm中將變量存儲到內存和內存中讀取出變量這樣的底層細節。
所有的變量都存儲在主內存中。
每股線程都有自己獨立的工作內存,里面保存該線程所使用到的變量副本(主內存中該變量的一份拷貝)。

添加圖片

4.兩條規定
線程對共享變量的所有操作都必須在自己的工作內存中進行,不能直接從主線程中獲取。
不同線程中間無法訪問其他線程中作內存中的變量,線程間變量值得傳遞需要通過主內存來完成。

5.共享變量可見性實現原理
線程1對共享變量的修改想要被線程2及時看到,必須經過如下2步操作:
把工作內存1中的更新過的共享變量刷新到主內存中;
將主內存中最新的共享變量的值更新到2的工作內存中。

添加圖片

6.要實現共享變量的可見性,必須保證兩點:
線程修改后的共享變量值能夠及時從工作內存刷新到主內存中;
其他線程能夠及時的把共享變量的最新值從主內存更新到自己的工作內存中。

7.Java語言層面支持的可見性實現原理方式:
》》synchronize
》》volatile

synchronized
能夠實現 代碼的原子性(同步)和 內存的可見性;
jmm對其的兩條規定:
線程解鎖前,必須把共享變量的最新值刷新到主內存中;
線程枷鎖前,將清空工作內存中的共享變量的值,從而使用共享變量時需要從主內存中重新讀取新的值。(枷鎖與解鎖需要是同一把鎖)。
線程解鎖前對共享線程變量的修改在下次枷鎖時對其他線程可見。

線程 執行互斥代碼的過程:
獲得互斥鎖;
清空工作內存;
從主內存拷貝變量的最新的值到工作內存;
執行代碼;
將更改后的共享變量的值刷新到主內存;
釋放互斥鎖。


導致共享變量在線程間不可見的原因:
線程的交叉執行;
重排序結合線程的交叉執行;
共享變量更新后的值沒有在工作內存與主內存及時更新。


volatile
保證變量的可見性,不能保證變量的符合操作原子性。
實現內存可見:
深入的說:通過加入內存屏障和禁止重排序優化實現。對其變量執行寫操作時,會在寫操作后加入一條store屏障指令;對其進行讀操作時,會在讀操作前加入一條load屏障指令。
通俗的說:volatile變量在每次被線程訪問時,都強迫從主線程中重讀該變量的值,而當該變量發生變化時,又會強迫線程將最新的值刷新到主內存中,這樣任何時刻,不同的線程總能看到該變量最新的值。

線程寫volatile變量的過程:
改變線程工作內存中volatile變量副本的值;
將改變后的副本的值從工作內存刷新到主內存。
線程讀volatile變量的過程:
從主內存中讀取volatile變量的最新值到線程的工作內存中;
從工作內存中讀取volatile變量的副本。


保證num++的原子性:
使用synchronized關鍵字
使用RentrantLock(java.util.concurrent.locks包下)
使用AtomicInterger(java.util.concurrent.atommic包下)

synchronized(this){
num++;
}

private Lock lock = new ReentrantLock();
lock.lock();
try{
num++;
}finally{
lock.unlock();
}


//實例化一個線程
new Thread(new Runnable(){
public void run(){
num++;
}
}).start();


//如果還有子線程在運行,主線程就讓出CPU資源,直到所有的子線程都運行完了,主線程再繼續向下執行。
while(Thread.activeCount()>1){
Thread.yield();
}


volatile的使用場景:
對變量的寫入操作不依賴其當前值:不滿足:num++;num = num*5;滿足 boolean值。
該變量沒有包含在其他變量的不變式中。


synchronize 與 volatile 比較
volatile不需要枷鎖,比synchronize更輕量級,不會堵塞程序;
從內存可見角度講,volatile讀相當於枷鎖,volatile寫相當於解鎖。
synchronize既能保證可見性,又能保障原子性,而volatile只能保障可見性,不能保證原子性。


共享數據的訪問權限必須定義為private

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM