在Java1.5之前,synchronized應該是最常用的java支援並發手段。那synchronized是怎麼做到的了,從java1.0開始,java中的每個對象就一個內部鎖。如果一個類的方法被synchronized關鍵字所修飾,那麼這個對象的鎖將保護整個方法。
舉例來說:
public synchronized void method(){
method body
}
等價於
public void method(){
this.intrinsicLock.lock();
try{
method body;
}finally(){
this.intrinsicLock.unlock();
}
}
從上面的程式碼範例可以看出,synchronized的使用方式是比較簡單的。這也導致了大量的初學者在碰到java編程的時候落入陷阱裡,認為既然synhronized可以搞定一切,那麼不管三七二十一,只要有並發可能性的地方,就加上synchronized的關鍵字,這顯然是不對的。在java對象中,這個java對象只有這一個內部鎖,其中一個synchronized方法擷取到了這個鎖,另外一個synchronized方法的調用將被阻塞。
即
class sync{
public synchronized void methodA(){};
public synchronized void methodB(){};
... ...
}
methodA 和methodB在初始就是互斥的,如果methodA和methodB進入互相等待,就很容易出現死結的情況。那如果碰到這種情況,應該怎麼做了。常用的方式是在方法內部建立一個無意義的對象,然後對這個無意義的對象加鍋。
package zl.study.concurrency.synchronize; public class Sync { private int i; public void plus(){ Object dummy = new Object(); synchronized(dummy){ i++; } } public void minus(){ Object dummy = new Object(); synchronized(dummy){ i--; } } }
另外需要注意的是將靜態類聲明為synchronized方法也是合法的。舉例來說,如果Sync有一個static synchronized方法,那麼這個方法被調用時,bank.class這個類對象本身在jvm中將被鎖住。