1. 程式人生 > >轉: 【Java並發編程】之十四:圖文講述同步的另一個重要功能:內存可見性

轉: 【Java並發編程】之十四:圖文講述同步的另一個重要功能:內存可見性

integer sdn 技術 訪問 span 另一個 edi int tro

轉載請註明出處:http://blog.csdn.net/ns_code/article/details/17288243

加鎖(synchronized同步)的功能不僅僅局限於互斥行為,同時還存在另外一個重要的方面:內存可見性。我們不僅希望防止某個線程正在使用對象狀態而另一個線程在同時修改該狀態,而且還希望確保當一個線程修改了對象狀態後,其他線程能夠看到該變化。而線程的同步恰恰也能夠實現這一點。

內置鎖可以用於確保某個線程以一種可預測的方式來查看另一個線程的執行結果。為了確保所有的線程都能看到共享變量的最新值,可以在所有執行讀操作或寫操作的線程上加上同一把鎖。下圖示例了同步的可見性保證。

技術分享

當線程A執行某個同步代碼塊時,線程B隨後進入由同一個鎖保護的同步代碼塊,這種情況下可以保證,當鎖被釋放前,A看到的所有變量值(鎖釋放前,A看到的變量包括y和x)在B獲得同一個鎖後同樣可以由B看到。換句話說,當線程B執行由鎖保護的同步代碼塊時,可以看到線程A之前在同一個鎖保護的同步代碼塊中的所有操作結果。如果在線程A unlock M之後,線程B才進入lock M,那麽線程B都可以看到線程A unlock M之前的操作,可以得到i=1,j=1。如果在線程B unlock M之後,線程A才進入lock M,那麽線程B就不一定能看到線程A中的操作,因此j的值就不一定是1。

現在考慮如下代碼:

[java] view plain copy
  1. public class MutableInteger
  2. {
  3. private int value;
  4. public int get(){
  5. return value;
  6. }
  7. public void set(int value){
  8. this.value = value;
  9. }
  10. }


以上代碼中,get和set方法都在沒有同步的情況下訪問value。如果value被多個線程共享,假如某個線程調用了set,那麽另一個正在調用get的線程可能會看到更新後的value值,也可能看不到。

通過對set和get方法進行同步,可以使MutableInteger成為一個線程安全的類,如下:

[java] view plain copy
  1. public class SynchronizedInteger
  2. {
  3. private int value;
  4. public synchronized int get(){
  5. return value;
  6. }
  7. public synchronized void set(int value){
  8. this.value = value;
  9. }
  10. }


對set和get方法進行了同步,加上了同一把對象鎖,這樣get方法可以看到set方法中value值的變化,從而每次通過get方法取得的value的值都是最新的value值。


轉: 【Java並發編程】之十四:圖文講述同步的另一個重要功能:內存可見性