1. 程式人生 > >執行緒-synchronized方法和同步塊的作用範圍;synchronized(this)和synchronized(obj)的區別

執行緒-synchronized方法和同步塊的作用範圍;synchronized(this)和synchronized(obj)的區別

原文:http://m.blog.csdn.net/blog/u010802573/38661719

參考資源:

http://www.cnblogs.com/oracleDBA/archive/2010/05/22/1741642.html

http://www.cnblogs.com/highriver/archive/2011/12/18/2291965.html

http://www.2cto.com/kf/200906/39293.html

http://wangym.iteye.com/blog/1265973

http://blog.csdn.net/zyplus/article/details/6672775

首先,解釋一下synchronzied作用

Synchronzied關鍵字的作用一個詞概括就是:執行緒同步。它可以用來修改物件中的方法,將物件加鎖。相當於不管哪一個執行緒A每次執行到這個方法時,都要檢查有沒有其它正在用這個方法的執行緒B(或者C D等),有的話要等正在使用這個方法的執行緒B(或者C D)執行完這個方法後再執行此執行緒A,沒有的話,直接執行。

然後,講講synchronzied語法

Synchronzied關鍵字包括兩種用法:synchronized 方法和 synchronized 塊。

1.synchronized方法

如:public synchronized void accessVal(int newVal);

synchronized 方法控制對類成員變數的訪問:每個類例項對應一把鎖,每個 synchronized方法都必須獲得呼叫該方法的類例項的鎖方能執行,否則所屬執行緒阻塞,方法一旦執行,就獨佔該鎖,直到從該方法返回時才將鎖釋放,此後被阻塞的執行緒方能獲得該鎖,重新進入可執行狀態。這種機制確保了同一時刻對於每一個類例項,其所有宣告為 synchronized的成員函式中至多隻有一個處於可執行狀態(因為至多隻有一個能夠獲得該類例項對應的鎖),從而有效避免了類成員變數的訪問衝突(只要所有可能訪問類成員變數的方法均被宣告為 synchronized)。在 Java中,不光是類例項,每一個類也對應一把鎖,這樣我們也可將類的靜態成員函式宣告為

 synchronized,以控制其對類的靜態成員變數的訪問。

2.synchronized

synchronized 方法是對整個方法進行加鎖。若將一個大的方法宣告為synchronized將會大大影響效率,典型地,若將執行緒類的方法 run()宣告為 synchronized ,由於線上程的整個生命期內它一直在執行,因此將導致它對本類任何 synchronized方法的呼叫都永遠不會成功。當然我們可以通過將訪問類成員變數的程式碼放到專門的方法中,將其宣告為 synchronized,並在主方法中呼叫來解決這一問題,但是 Java為我們提供了更好的解決辦法,那就是 synchronized 塊。

如:synchronized(syncObject) {

//允許訪問控制的程式碼

}

synchronized 塊是這樣一個程式碼塊,其中的程式碼必須獲得物件 syncObject(如前所述,可以是類例項或類)的鎖方能執行,具體機制同前所述。由於可以針對任意程式碼塊,且可任意指定上鎖的物件,故靈活性較高。

1.當兩個併發執行緒訪問同一個物件object中的這個synchronized(this)同步程式碼塊時,一個時間內只能有一個執行緒得到執行。另一個執行緒必須等待當前執行緒執行完這個程式碼塊以後才能執行該程式碼塊。
2.然而,當一個執行緒訪問object的一個synchronized(this)同步程式碼塊時,另一個執行緒仍然可以訪問該object中的非synchronized(this)同步程式碼塊。
3.尤其關鍵的是,當一個執行緒訪問object的一個synchronized(this)同步程式碼塊時,其他執行緒對object中所有其它synchronized(this)同步程式碼塊的訪問將被阻塞。
4.第三個例子同樣適用其它同步程式碼塊。也就是說,當一個執行緒訪問object的一個synchronized(this)同步程式碼塊時,它就獲得了這個object的物件鎖。結果,其它執行緒對該object物件所有同步程式碼部分的訪問都被暫時阻塞。
5.以上規則對其它物件鎖同樣適用.

下面來說一下synchronized(this)和synchronized(obj)的區別:

synchronized(this)中this指呼叫該方法的引用物件,obj則可以為任意 引用物件;

Java語法規定,任何執行緒執行同步方法、同步程式碼塊 之前,必須先獲取對應的監視器JAVA的synchronized()方法類似於作業系統概念中的互斥記憶體塊,在JAVA中的Object型別中,都是帶有一個記憶體鎖的,在有執行緒獲取該記憶體鎖後,其它執行緒無法訪問該記憶體,從而實現JAVA中簡單的同步、互斥操作。明白這個原理,就能理解為什麼synchronized(this)與synchronized(static XXX)的區別了,synchronized就是針對記憶體區塊申請記憶體鎖,this關鍵字代表類的一個物件,所以其記憶體鎖是針對相同物件的互斥操作,而static成員屬於類專有,其記憶體空間為該類所有成員共有,這就導致synchronized()對static成員加鎖,相當於對類加鎖,也就是在該類的所有成員間實現互斥,在同一時間只有一個執行緒可訪問該類的例項。如果只是簡單的想要實現在JAVA中的執行緒互斥,明白這些基本就已經夠了。但如果需要線上程間相互喚醒的話就需要藉助Object.wait(), Object.nofity()了。

synchronized(class)很特別,它會讓另一個執行緒在任何需要獲取class做為monitor的地方等待.class與this做為不同的監視器可以同時使用,不存在一個執行緒獲取了class,另一個執行緒就不能獲取該class的一切例項.

根據下面的程式碼自行修改,分別驗證下面的幾種情況:

synchronized(class)
synchronized(this)
->執行緒各自獲取monitor,不會有等待.
synchronized(this)
synchronized(this)
->如果不同執行緒監視同一個例項物件,就會等待,如果不同的例項,不會等待.
synchronized(class)
synchronized(class)
->如果不同執行緒監視同一個例項或者不同的例項物件,都會等待.