不能夠!!!java
多個線程訪問同一個類的synchronized方法時, 都是串行執行的 ! 就算有多個cpu也不例外 ! synchronized方法使用了類java的內置鎖, 即鎖住的是方法所屬對象自己. 同一個鎖某個時刻只能被一個執行線程所獲取, 所以其餘線程都得等待鎖的釋放. 所以就算你有多餘的cpu能夠執行, 可是你沒有鎖, 因此你仍是不能進入synchronized方法執行, CPU所以而空閒. 若是某個線程長期持有一個競爭激烈的鎖, 那麼將致使其餘線程都因等待所的釋放而被掛起, 從而致使CPU沒法獲得利用, 系統吞吐量低下. 所以要儘可能避免某個線程對鎖的長期佔有 !
public class SyncMethod { public synchronized void syncMethod2() { try { System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@ (syncMethod2, 已經獲取內置鎖`SyncMethod.this`)"); Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@ (syncMethod2, 即將釋放內置鎖`SyncMethod.this`)"); } public synchronized void syncMethod1() { System.out.println("######################## (syncMethod1, 已經獲取內置鎖`SyncMethod.this`, 並即將退出)"); } static class Thread1 extends Thread { SyncMethod syncMethod; public Thread1(SyncMethod syncMethod) { this.syncMethod = syncMethod; } @Override public void run() { syncMethod.syncMethod2(); } } static class Thread2 extends Thread { SyncMethod syncMethod; public Thread2(SyncMethod syncMethod) { this.syncMethod = syncMethod; } @Override public void run() { System.out.println("Thread2 running ..."); syncMethod.syncMethod1(); } } public static void main(String[] args) throws InterruptedException { SyncMethod syncMethod = new SyncMethod(); Thread1 thread1 = new Thread1(syncMethod); Thread2 thread2 = new Thread2(syncMethod); thread1.start(); //先執行, 以便搶佔鎖 Thread.sleep(500); //放棄cpu, 讓thread1執行, 以便獲的鎖 thread2.start(); //在syncMethod1()方法得到鎖時, 看看syncMethod2()方法可否執行 /* 可否併發執行同一個對象不一樣的synchronized方法, 即看看可否同時進入一個對象synchronized方法塊 1. 建立一個有兩個synchronized方法的對象`syncMethod` 2. 先啓動一個線程(Thread1), 並讓其進入syncMethod對象的sychronized方法(syncMethod1)內, 並使其停在synchronized方法內 3. 再啓動一個線程(Thread2), 並執行syncMethod對象的一個synchronized方法(syncMethod2), 看看可否進入此方法內 輸出以下: @@@@@@@@@@@@@@@@@@@@@@@@ (syncMethod2, 已經獲取內置鎖`SyncMethod.this`) Thread2 running ... @@@@@@@@@@@@@@@@@@@@@@@@ (syncMethod2, 即將釋放內置鎖`SyncMethod.this`) ######################## (syncMethod1, 已經獲取內置鎖`SyncMethod.this`, 並即將退出) 結果分析: 觀察顯示, 在輸出`Thread2 running ...`後會暫停數秒(Thread2沒法得到鎖而被掛起, 由於鎖已經被Thread1持有). 若是不一樣線程能夠同時訪問同一個對象不一樣synchronized方法的話, 在有足夠cpu時間片時(Thread1在調用syncMethod1時使用Thread.sleep放棄了cpu), Thread2調用的syncMethod2方法應該立刻執行, 也就是syncMethod2方法中的語句在`Thread2 running ...`語句輸出後立刻輸出, 而不是等待數秒才輸出 (應爲此時沒有其餘線程跟Thread2競爭cpu, 何況如今的電腦都不僅一個cpu), 所以得出結論: "不一樣線程不能同時執行一個對象的不一樣synchronized方法" 其實此結論是顯而易見的, 原理前面已經闡明, 此處再也不贅述. */ } }
下面是一些關於使用鎖的一些建議:
爲了不對鎖的競爭, 你可使用鎖分解,鎖分段以及減小線程持有鎖的時間, 若是上訴程序中的syncMethod1和syncMethod2方法是兩個不相干的方法(請求的資源不存在關係), 那麼這兩個方法能夠分別使用兩個不一樣的鎖, 改造後的SyncMethod類以下:併發
public class SyncMethod { private Object lock1 = new Object(); private Object lock2 = new Object(); public void syncMethod2() { synchronized (lock1) { try { System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@ (syncMethod2, 已經獲取內置鎖`SyncMethod.this`)"); Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@ (syncMethod2, 即將釋放內置鎖`SyncMethod.this`)"); } } public void syncMethod1() { synchronized (lock2) { System.out.println("######################## (syncMethod1, 已經獲取內置鎖`SyncMethod.this`, 並即將退出)"); } } }
改造以後Thread1和Thread2就不會發生, 因爲鎖競爭而掛起的狀況了.ide
固然, 若是syncMethod1中耗時操做與鎖定的資源無關, 那麼也能夠將耗時操做移出同步塊. 在上述改造的基礎上對syncMethod1的進一步改造以下:this
public void syncMethod2() { synchronized (lock1) { System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@ (syncMethod2, 已經獲取內置鎖`SyncMethod.this`)"); System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@ (syncMethod2, 即將釋放內置鎖`SyncMethod.this`)"); } //將耗時操做移出同步塊 try { Thread.sleep(5000);//與同步使用的資源無關的耗時操做 } catch (InterruptedException e) { e.printStackTrace(); } }