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

加鎖(synchronized同步)的功能不單單侷限於互斥行爲,同時還存在另一個重要的方面:內存可見性。咱們不只但願防止某個線程正在使用對象狀態而另外一個線程在同時修改該狀態,並且還但願確保當一個線程修改了對象狀態後,其餘線程可以看到該變化。而線程的同步偏偏也可以實現這一點。java

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

20131212211029125.jpgthis

當線程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。線程

​ 如今考慮以下代碼:code

public class  MutableInteger  
{  
    private int value;  
  
    public int get(){  
        return value;  
    }  
    public void set(int value){  
        this.value = value;  
    }  
}

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

​ 經過對set和get方法進行同步,可使MutableInteger成爲一個線程安全的類,以下:內存

public class  SynchronizedInteger  
{  
    private int value;  
  
    public synchronized int get(){  
        return value;  
    }  
    public synchronized void set(int value){  
        this.value = value;  
    }  
}

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

相關文章
相關標籤/搜索