Java并发:线程共享变量可见性原理
0、線程安全性:線程安全性包括兩個方面,①可見性。②原子性。
0.1、線程之間的通信:線程的通信是指線程之間以何種機制來交換信息。在命令式編程中,線程之間的通信機制有兩種共享內存和消息傳遞。
(1)在共享內存的并發模型里,線程之間共享程序的公共狀態,線程之間通過寫-讀內存中的公共狀態來隱式進行通信,典型的共享內存通信方式就是通過共享對象進行通信。
(2)在消息傳遞的并發模型里,線程之間沒有公共狀態,線程之間必須通過明確的發送消息來顯式進行通信,在java中典型的消息傳遞方式就是wait()和notify()。
?????????????????????????????Java內存模型
1、可見性:一個線程對共享變量值得修改,能夠及時地被其他線程看到。
2、共享變量:如果一個變量在多個線程的工作內存都存在副本,那么這個變量就是這幾個線程的共享變量。
3、線程的工作內存:JMM抽象出的一種內存模型。
???首先,所有的變量都是儲存在主內存中的,每個線程都有自己的獨立的工作內存,里面保存的是該線程使用到的變量的副本(它們是內存這些變量的一份拷貝,而變量的原件是保存在主內存的)。
???線程修改的變量的值是修改的該線程的工作內存中的變量的副本,然后再將修改后的值刷新到主內存中。
???此時,其他線程能否及時地看到主內存中該變量的更新的值,這時就涉及到了“可見性”問題。
???
4、JMM中有兩條規定:
???(1)線程對共享變量的所有操作都必須在自己的工作內存中進行,不能直接在主內存中讀寫;
???(2)不同的線程之間不能直接訪問其他線程工作內存的變量,線程之間變量值得傳遞只能通過主內存來傳遞。
???
5、實現共享變量的可見性,必須保證兩點:
???(1)線程修改后的共享變量值能夠及時從線程工作內存中刷新到主內存中;
???(2)其他線程能夠及時把共享變量的在、最新值從主內存更新到自己的工作內存中。
???
6、java支持的可見性實現的兩種方式:synchronized、volatile。
(1)synchronized能夠保證同步方法或同步代碼塊中變量的復合操作的原子性;也能保證變量的可見性。
(2)volatile不能保證變量的復合操作的原子性;只能保證變量的可見性。
7、JMM關于synchronized的兩條規定(synchronized如何實現內存可見性):
(1)線程加鎖時,將清空工作內存中共享變量的值,從而使用共享變量時需要從主內存中重新讀取最新的值。
(2)線程解鎖時,必須把共享變量的最新值刷新到主內存中。
8、synchronized線程執行互斥代碼的六個過程:
(1)獲得互斥鎖;
(2)清空工作內存;
(3)從主內存中拷貝變量的最新值到工作內存;
(4)執行代碼;
(5)將更改后的共享變量的值刷新到主內存;
(6)釋放互斥鎖。
9、指令重排序:重排序不會對單線程帶來內存可見性問題。但是多線程交互時,指令重排序可能會造成內存可見性問題。
10、volatile如何實現內存可見性:通過加入內存屏障和禁止重排序來優化實現的。
(1)對volatile變量執行寫操作時,會在寫操作后加入一條store屏障指令;
(2)對volatile變量執行讀操作時,會在讀操作前加入一條load屏障指令。
11、volatile如何實現內存可見性:
(1)線程寫volatile變量的過程:
????1.改變線程工作內存中volatile變量副本的值
????2.將改變后的副本的值從工作內存刷新的主內存
(2)線程讀volatile變量的過程:
???1.從主內存中讀取volatile變量的最新值到線程的工作內存中
???2.從工作內存中讀取volatile變量的副本
???
12、volatile不能保證變量復合操作的原子性:
private int number = 0;??????????????????????????????
number++; //不是原子操作?
number++的步驟??????????????????????????????????????
1.讀取number的值??
2.將number的值加1??
3.寫入最新的number的值?????????????????????????????
????synchronized(this){??//加入synchronized,變為原子操作
???????number++;
????}
private volatile int number = 0;//變為volatile變量,無法保證原子性?? ?
?
?13、volatile和synchronized的區別
(1)volatile本質是在告訴jvm當前變量在寄存器(工作內存)中的值是不確定的,需要從主存中讀取; synchronized則是鎖定當前變量,只有當前線程可以訪問該變量,其他線程被阻塞住。
(2)volatile僅能使用在變量級別;synchronized則可以使用在變量、方法、和類級別的。
(3)volatile僅能實現變量的修改可見性,不能保證原子性;而synchronized則可以保證變量的修改可見性和原子性。
(4)volatile不會造成線程的阻塞;synchronized可能會造成線程的阻塞。
(5)volatile標記的變量不會被編譯器優化;synchronized標記的變量可以被編譯器優化。
?
總結
以上是生活随笔為你收集整理的Java并发:线程共享变量可见性原理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 奥迪电动车 折戟在中国
- 下一篇: Java--对象内存布局