synchronized void f(){/*....*/} synchronized void g(){/*....*/}
全部的對象都自動含有單一的鎖(也稱爲監視器,前面閱讀Thread源碼有提到監視器)。當在對象上調用任意synchronized方法時,此對象都被加鎖,這時該對象上的其餘synchronized方法只有等到前一個方法調用完畢釋放了鎖以後才能被調用。對於前面的方法,若是某個任務對對象調用了f(),對於同一個對象而言,只有等到f()調用結束並釋放了鎖以後,其餘任務才能調用f()或者g()。因此,對於某個特定的對象來講,其全部的synchronized方法共享同一個鎖,這能夠被用來防止多個任務同時訪問被編碼對象內存。java
一個任務能夠屢次得到對象鎖,也就是鎖可重入。是指,一個方法在同一個對象上調用了第二個方法,後者又調用了同一個對象上的另一個方法,就是發生鎖的重入。JVM負責跟蹤對象被枷鎖的次數。若是一個對象被解鎖也就說鎖被徹底釋放,其計數變爲0。在任務第一次給對象加鎖時,計數變爲1。每當這個相同的任務在這個對象上得到鎖的時候,計數都會遞增。顯然,只有先得到了鎖的任務才能容許繼續得到鎖。每當任務離開一個synchronized方法,計數遞減,當計數爲0的時候,鎖被徹底釋放,此時別的任務就能夠繼續使用此資源。併發
針對每一個類,也有一個鎖,做爲Class對象的一部分,因此synchronized static方法能夠在類的範圍內防止對static數據的併發訪問。ide
基本上,當你使用關鍵字synchronized關鍵字時,須要的代碼量更少,而且用戶出現錯誤的機率更低,所以一般只有解決特殊任務時纔會使用到現實的Lock對象。好比,用synchronized不能嘗試獲取鎖而且最終會獲取鎖失敗,或者嘗試着獲取鎖等待一段時間,這些須要concurrent類庫this
abstract class IntGenerator{ private volatile boolean canceled = false; public abstract int next(); public void cancel(){this.canceled =true;} public boolean isCanceled(){return this.canceled;} } class EvenChecker implements Runnable{ private IntGenerator generator; private final int id; public EvenChecker(IntGenerator g,int ident){ generator = g; id = ident; } public void run() { while (!generator.isCanceled()){ int val = generator.next(); if(val%2 != 0){ System.out.println(val + " not even!"); generator.cancel(); } } } public static void test(IntGenerator gp,int count){ System.out.println("Press Contrl-C to exit"); ExecutorService exec = Executors.newCachedThreadPool(); for(int i=0;i<count;i++){ exec.execute(new EvenChecker(gp,i)); } exec.shutdown(); } public static void test(IntGenerator gp){ test(gp,10); } } class SynchronizedEvenGenerator extends IntGenerator{ private int currentVlaue = 0; public synchronized int next() { ++currentVlaue; //當不使用synchronized修飾next方法時,調用該方法能夠促使線程同步調用異常發生 //Thread.yield(); //一樣說明一個問題Thread。yield即使是讓出cpu可是並無釋放鎖 ++currentVlaue; return currentVlaue; } } class MutexEvenGenerator extends IntGenerator{ private int currentVlaue = 0; private Lock lock = new ReentrantLock(); public int next() { lock.lock(); try{ ++currentVlaue; //當不使用synchronized修飾next方法時,調用該方法能夠促使線程同步調用異常發生 Thread.yield(); //一樣說明一個問題Thread。yield即使是讓出cpu可是並無釋放鎖 ++currentVlaue; return currentVlaue; }finally { lock.unlock(); } } } public class NesttyMain implements Serializable{ public static void main(String[] args){ // EvenChecker.test(new SynchronizedEvenGenerator()); EvenChecker.test(new MutexEvenGenerator()); } }