多線程——synchronized關鍵字詳解

1.    把synchronized看成函數修飾符時,示例代碼以下:
public synchronized void method(){
//….
}
這也就是同步方法,那這時synchronized鎖定的是哪一個對象呢?他鎖定的是調用這個同步方法對象。也就是說,當一個對象P1在不一樣的線程中執行這個同步方法時,他們之間會出現阻塞,達到同步的效果。可是這個對象所屬的Class所產生的另外一對象P2卻可以任意調用這個被加了synchronized關鍵字的方法。數組

2.同步塊,示例代碼以下:
public void method(SomeObject so) {
synchronized(so)
{
//…..
}
}
這時,鎖就是so這個對象,誰拿到這個鎖誰就可以運行他所控制的那段代碼。當有一個明確的對象做爲鎖時,就可以這樣寫程式,但當沒有明確的對象做爲鎖,只是想讓一段代碼同步時,可以建立一個特別的instance變量(它得是個對象)來充當鎖:
class Foo implements Runnable
{
private byte[] lock = new byte[0]; // 特別的instance變量
Public void method()
{
synchronized(lock) { //… }
}
//…..
}
注:零長度的byte數組對象建立起來將比任何對象都經濟。查看編譯後的字節碼:生成零長度的byte[]對象只需3條操做碼,而Object lock = new Object()則須要7行操做碼。
3.將synchronized做用於static 函數,示例代碼以下:
Class Foo
{
public synchronized static void method1() // 同步的static 函數
{
//….
}
public void method2()
{
synchronized(Foo.class) // class literal(類名稱字面常量)
}
}
代碼中的method2()方法是把class literal做爲鎖的狀況,他和同步的static函數產生的效果是相同的,取得的鎖很特別,是當前調用這個方法的對象所屬的類(Class類,而再也不是由這個Class產生的某個具體對象了)函數


JAVA中synchronized關鍵字可以做爲函數的修飾符,也可做爲函數內的語句,也就是平時說的同步方法和同步語句塊。假如再細的分類,synchronized可做用於instance變量、object reference(對象引用)、static函數和class literals(類名稱字面常量)身上。synchronized void f() { /* body */ } void f() { synchronized(this) { /* body */ } }是徹底等價的。
this

synchronized(class)很特別,它會讓另外一個線程在任何須要獲取class作爲monitor的地方等待。class與this做爲不一樣的監視器能夠同時使用,不存在一個線程獲取了class,另外一個線程就不能獲取該class的一切實例。spa

  1. 對於實例同步方法,鎖是當前實例對象。線程

  2. 對於靜態同步方法,鎖是當前對象的Class對象。code

  3. 對於同步方法塊,鎖是Synchonized括號裏配置的對象。orm

class與this的幾種狀況:
synchronized(class)
synchronized(this)
對象

線程各自獲取monitor,不會有等待。同步

synchronized(this)
synchronized(this)
it

若是不一樣線程監視同一個實例對象,就會等待;若是不一樣的實例,不會等待。

synchronized(class)synchronized(class)若是不一樣線程監視同一個實例或者不一樣的實例對象,都會等待。

相關文章
相關標籤/搜索