public class Sync { public synchronized void test() { System.out.println("test start"); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("test end"); } }
#html
public class MyThread extends Thread{ public void run() { Sync sync = new Sync(); sync.test(); } public static void main(String[] args) { for (int i = 0; i < 3; ++i) { Thread thread = new MyThread(); thread.start(); } } }
執行結果程序員
test start test start test start test end test end test end
現象swift
在MyThread中,每次都new一個新的Sync對象,能夠看到代碼塊test雖然被加了synchonized可是仍是並行執行的,初步結論:鎖住的不是代碼塊安全
public class MyThread2 extends Thread{ public Sync sync; MyThread2(Sync sync) { this.sync = sync; } public void run() { System.out.println("hi...."); sync.test(); } public static void main(String[] args) { Sync sync = new Sync(); for (int i = 0; i < 3; ++i) { Thread thread = new MyThread2(sync); thread.start(); } }
執行結果bash
hi.... test start hi.... hi.... test end test start test end test start test end
現象併發
能夠看到當他們共用一個對象的時候,synchonized起了做用,這塊代碼是串行執行的性能
鎖住的是對象this
解決也很簡單,只要鎖住同一個對象就好了。例如:synchronized後的括號中鎖同一個固定對象,這樣就好了。spa
這樣是沒問題,可是,比較多的作法是讓synchronized鎖這個類對應的Class對象。.net
public class Sync2 { public void test() { synchronized (Sync2.class) { System.out.println("test start"); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("test end"); } } }
#
public class MyThread3 extends Thread{ public void run() { Sync2 sync = new Sync2(); sync.test(); } public static void main(String[] args) { for (int i = 0; i < 3; ++i) { Thread thread = new MyThread3(); thread.start(); } } }
執行結果
test start
test end
test start
test end
test start
test end
雖然synchronized已經做爲一個關鍵字被固化在Java語言中了,但它只提供了一種至關保守的線程安全策略,且該策略開放給程序員的控制能力極弱