synchronized基礎
synchronized 例子
例1,沒有同步的時候運行同一個物件的同一個方法的結果:
public class TestSyn { public synchronized void showMsg() { try { for (int i = 0; i < 3; i++) { System.out.println(Thread.currentThread().getName() + ":" + i); Thread.sleep(200); } } catch (InterruptedException e) { e.printStackTrace(); } } public static void main(String[] args) { TestSyn testSyn = new TestSyn(); ExecutorService executorService = Executors.newFixedThreadPool(10); Runnable runnable = new Runnable() { @Override public void run() { testSyn.showMsg(); } }; Runnable runnable2 = new Runnable() { @Override public void run() { testSyn.showMsg(); } }; executorService.execute(runnable); executorService.execute(runnable2); executorService.shutdown(); } }
結果:
可以看到,是同時在執行一個方法裡面的內容,沒有進行同步
例2,當我們其它不變,只是在方法上加synchronized後:
public class TestSyn { public synchronized void showMsg() { try { for (int i = 0; i < 3; i++) { System.out.println(Thread.currentThread().getName() + ":" + i); Thread.sleep(200); } } catch (InterruptedException e) { e.printStackTrace(); } } }
結果:
可以看到是一個方法執行完後再執行下一次,已經進行了同步
例3,我們在新增另外一個synchronized後觀察執行結果:
public class TestSyn { public synchronized void showMsg() { try { for (int i = 0; i < 3; i++) { System.out.println(Thread.currentThread().getName() + ":" + i); Thread.sleep(200); } } catch (InterruptedException e) { e.printStackTrace(); } } public synchronized void showMsg2() { try { for (int i = 0; i < 3; i++) { System.out.println(Thread.currentThread().getName() + ":" + i); Thread.sleep(200); } } catch (InterruptedException e) { e.printStackTrace(); } } public static void main(String[] args) { TestSyn testSyn = new TestSyn(); ExecutorService executorService = Executors.newFixedThreadPool(10); Runnable runnable = new Runnable() { @Override public void run() { testSyn.showMsg(); } }; Runnable runnable2 = new Runnable() { @Override public void run() { testSyn.showMsg2(); } }; executorService.execute(runnable); executorService.execute(runnable2); executorService.shutdown(); } }
發不同的兩個方法依然進行了同步。
我們重新新建一個物件,執行相同的同步函式觀察結果:
public class TestSyn { public synchronized void showMsg() { try { for (int i = 0; i < 3; i++) { System.out.println(Thread.currentThread().getName() + ":" + i); Thread.sleep(200); } } catch (InterruptedException e) { e.printStackTrace(); } } public static void main(String[] args) { TestSyn testSyn = new TestSyn(); TestSyn testSyn2 = new TestSyn(); ExecutorService executorService = Executors.newFixedThreadPool(10); Runnable runnable = new Runnable() { @Override public void run() { testSyn.showMsg(); } }; Runnable runnable2 = new Runnable() { @Override public void run() { testSyn2.showMsg(); } }; executorService.execute(runnable); executorService.execute(runnable2); executorService.shutdown(); } }
發現不同物件的同一個方法沒有進行同步
例4,我們換成一個static方法新增synchronized後:
public class TestSyn { public synchronized void showMsg() { try { for (int i = 0; i < 3; i++) { System.out.println(Thread.currentThread().getName() + ":" + i); Thread.sleep(200); } } catch (InterruptedException e) { e.printStackTrace(); } } public synchronized static void showMsg2() { try { for (int i = 0; i < 3; i++) { System.out.println(Thread.currentThread().getName() + ":" + i); Thread.sleep(200); } } catch (InterruptedException e) { e.printStackTrace(); } } public static void main(String[] args) { TestSyn testSyn = new TestSyn(); ExecutorService executorService = Executors.newFixedThreadPool(10); Runnable runnable = new Runnable() { @Override public void run() { testSyn.showMsg(); } }; Runnable runnable2 = new Runnable() { @Override public void run() { TestSyn.showMsg2(); } }; executorService.execute(runnable); executorService.execute(runnable2); executorService.shutdown(); } }
發現又沒有進行同步了。
結論:
1.某個物件例項內,synchronized aMethod(){}關鍵字可以防止多個執行緒訪問物件的synchronized方法(如果一個物件有多個synchronized方法,只要一個執行緒訪問了其中的一個synchronized方法,其它執行緒不能同時訪問這個物件中任何一個synchronized方法)。這時,不同的物件例項的synchronized方法是不相干擾的。也就是說,其它執行緒照樣可以同時訪問相同類的另一個物件例項中的synchronized方法
2.是某個類的範圍,synchronized static aStaticMethod{}防止多個執行緒同時訪問這個類中的synchronized static 方法。它可以對類的所有物件例項起作用
3.如果同一物件兩個synchronized方法一個是非static方法和static方法,是不相干擾的
4.synchronized關鍵字是不能繼承的,也就是說,基類的方法synchronized f(){} 在繼承類中並不自動是synchronized f(){},而是變成了f(){}。繼承類需要你顯式的指定它的某個方法為synchronized方法