多線程三大特性:多線程
可見性、原子性、有序性ide
synchronize的特性:spa
一、同一時刻只有一個線程訪問臨界資源線程
二、其它未獲取到鎖執行權的線程必須排隊等待code
三、保證共享資源的原子性、可見性和有序性對象
四、進入synchronized範圍內自動加鎖,synchronized做用域外鎖自動消除,即便異常也會釋放鎖blog
synchronize加鎖的方式:資源
-
對於普通同步方法,鎖是當前實例對象。作用域
-
對於靜態同步方法,鎖是當前類的Class對象。同步
-
對於同步方法塊,鎖是Synchonized括號裏配置的對象。
經過具體的例子來看一下
首先是普通方法:
class NoSyncTest { public void method1() { Log.i("sync", "method 1 start"); try { Log.i("sync", "method 1 execute"); Thread.sleep(3000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } Log.i("sync", "method 1 end"); } public void method2() { Log.i("sync", "method 2 start"); try { Log.i("sync", "method 2 execute"); Thread.sleep(500); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } Log.i("sync", "method 2 end"); } } private void noSyncTest() { final NoSyncTest test = new NoSyncTest(); Thread thread1 = new Thread(new Runnable() { @Override public void run() { test.method1(); } }); Thread thread2 = new Thread(new Runnable() { @Override public void run() { test.method2(); } }); thread1.start(); thread2.start(); }
這是一個沒有任何同步的方法,NoSyncTest這個類有兩個方法method1和method2,分別執行睡3s和0.5s的動做,而後再兩個線程中分別調用這個類的實例test的兩個方法,看一下結果:
能夠看到method2和method1同時執行,method2由於sleep的時間短因此先結束。
再看一下普通方法同步:
class MethodSyncTest { public synchronized void method1() { Log.i("sync", "method 1 start"); try { Log.i("sync", "method 1 execute"); Thread.sleep(3000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } Log.i("sync", "method 1 end"); } public synchronized void method2() { Log.i("sync", "method 2 start"); try { Log.i("sync", "method 2 execute"); Thread.sleep(500); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } Log.i("sync", "method 2 end"); } } private void MethodSyncTest() { final MethodSyncTest test = new MethodSyncTest(); Thread thread1 = new Thread(new Runnable() { @Override public void run() { test.method1(); } }); Thread thread2 = new Thread(new Runnable() { @Override public void run() { test.method2(); } }); thread1.start(); thread2.start();
synchronize修飾的method1和method2,其餘不變,看一下結果:
method1先執行而後3s以後結束了method2纔開始執行。(注意這個地方不能new 不一樣的對象來調用方法,由於修飾普通方法本質是對對象的同步加鎖。)
看一下第三種靜態同步方法:
static class StaticMethodSyncTest { public static synchronized void method1() { Log.i("sync", "method 1 start"); try { Log.i("sync", "method 1 execute"); Thread.sleep(3000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } Log.i("sync", "method 1 end"); } public static synchronized void method2() { Log.i("sync", "method 2 start"); try { Log.i("sync", "method 2 execute"); Thread.sleep(500); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } Log.i("sync", "method 2 end"); } public static synchronized void method3() { Log.i("sync", "method 3 start"); try { Log.i("sync", "method 3 execute"); Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } Log.i("sync", "method 3 end"); } } private void StaticMethodSyncTest() { final StaticMethodSyncTest test1 = new StaticMethodSyncTest(); final StaticMethodSyncTest test2 = new StaticMethodSyncTest(); Thread thread1 = new Thread(new Runnable() { @Override public void run() { test1.method1(); } }); Thread thread2 = new Thread(new Runnable() { @Override public void run() { test2.method2(); } }); Thread thread3 = new Thread(new Runnable() { @Override public void run() { StaticMethodSyncTest.method3(); } }); thread1.start(); thread2.start(); thread3.start(); }
static修飾方法至關於這個方法是類方法,能夠直接經過類名.方法名調用。咱們在這new出了test1和test2兩個對象分別調用method1和method2,以及經過類名.方法名調用method3,看一下結果
method一、method二、method3順序執行。(同步靜態方法的本質是鎖的當前類)