一:不可見的原因
上一部分,根據代碼可以知道,產生不可見的原因有兩點:
1:CPU高速緩存會造成極短時間內數據的不可見
2:指令重排是導致不可見的主要原因
二:Java內存模型(JMM)
java內存模型主要是描述多線程程序的語義,多個線程對數據進行了修改,該讀取哪個的問題;Java內存模型並沒有規定如何去實現多線程程序,只是制定了一些合法行爲,即規則;Java內存模型對內存分爲工作內存和主內存,也就是棧內存和堆內存。
三:線程間的操作
java內存模型只規定線程間的操作,有以下幾種:read,write,volidate read,volidate write,線程start和start的線程的第一步操作,線程結束。
衝突和數據競爭:衝突就是線程間,有一個讀操作和一個寫操作,造成了衝突
四:JMM規則
1:同步規則
1.1 volidate的寫操作,對後續volidate的讀操作同步。
也就是說用volidate修飾的變量,寫入後,對其他線程是可見的。
1.2 unlock之後的操作,對後續的lock同步。
加鎖和解鎖不能重排序,也不能緩存,和volidate一樣,t1線程釋放鎖之後,對後續的加鎖是可見的。
1.3 t1線程的start操作,對t1的第一步操作同步。
也就是說,再主線程內啓動t1,對t1線程內部的操作是可見的。其實就是t1線程再啓動之前是NEW狀態,主線程把t1線程實例化後,主內存中保存了t1的狀態信息,start之後,t1線程的狀態變爲RUNNABLE,這個狀態對t1是可見的,不能夠緩存。
1.4 t1線程最後一步的操作,對後續的線程是可見的。
和1.3一樣,也是在主內存中的狀態信息是可見的,不能被緩存。
1.5 t1線程的interrupt操作,對其他線程是同步的。
interrupt操作後,對其他線程是可見的。
2:happens-before(先行發生原則)
2.1 volidate的寫操作,happens-before其他線程的讀操作,即寫操作發生在讀操作之前。
2.2 線程的unlock操作,happens-before其他線程的lock操作。
2.3 線程的start操作,happens-before此線程的所有操作。
2.4 若在t1線程中使用了t2.join,那麼t2的操作對t1是可見的。
2.5 若A happens-before B,B happens-before C,那麼A happens-before C。