線程安全之可見性(二)

一:不可見的原因

上一部分,根據代碼可以知道,產生不可見的原因有兩點:

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。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章