同步方法與同步塊的區別
阿新 • • 發佈:2019-02-03
java使用synchronized同步,分為四種情況:
例項方法同步
例項方法中同步塊
靜態方法同步
靜態方法中同步塊
我們從兩個方面來說他們的不同,一個是同步方法和同步塊的區別,一個是靜態和非靜態的區別。
同步方法就是在方法前加關鍵字synchronized,然後被同步的方法一次只能有一個執行緒進入,其他執行緒等待。而同步方法則是在方法內部使用大括號使得一個程式碼塊得到同步。同步塊會有一個同步的”目標“,使得同步塊更加靈活一些(同步塊可以通過”目標“決定需要鎖定的物件)。一般情況下,如果此”目標“為this,那麼同步方法和同步塊沒有太大的區別。
另外,通過反編譯可以看出,同步塊比同步方法多了兩個指令。因此同步方法是比同步塊要快一些。
非靜態和靜態的區別主要在於(以同步方法為例):非靜態的同步方法是鎖定類的例項的,而靜態的同步方法是鎖定類的;
也就是說,對於非靜態的同步方法,在同一時刻,一個類的一個例項中,只有一個執行緒能進入同步的方法。但是對於多個例項,每一個例項的一個執行緒都可以進入同一同步的方法。
Demo1:一個例項的多個執行緒,一次只能有一個執行緒進入非靜態同步的方法。
package SynchronizedTest; /** * Created by carrot on 16/8/31. */ public class SyncFunc { public synchronized void func1() { System.out.println(Thread.currentThread().getName() + " is running"); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " is stop"); } public static void main(String[] args) { NewThread newThread1 = new NewThread(); NewThread newThread2 = new NewThread(); NewThread newThread3 = new NewThread(); newThread1.start(); newThread2.start(); newThread3.start(); } } class NewThread extends Thread { static SyncFunc syncFunc = new SyncFunc(); @Override public void run() { syncFunc.func1(); } }
結果:
Thread-0 is running
Thread-0 is stop
Thread-2 is running
Thread-2 is stop
Thread-1 is running
Thread-1 is stop
從結果可見,每次只能有一個執行緒進入非靜態同步的方法。
Demo2:多個例項的執行緒能同時進入非靜態同步的方法。
package SynchronizedTest; /** * Created by carrot on 16/8/31. */ public class SyncFunc { public synchronized void func1() { System.out.println(Thread.currentThread().getName() + " is running"); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " is stop"); } public static void main(String[] args) { NewThread newThread1 = new NewThread(); NewThread newThread2 = new NewThread(); NewThread newThread3 = new NewThread(); newThread1.start(); newThread2.start(); newThread3.start(); } } class NewThread extends Thread { SyncFunc syncFunc = new SyncFunc(); @Override public void run() { syncFunc.func1(); } }
結果:
Thread-0 is running
Thread-1 is running
Thread-2 is running
Thread-0 is stop
Thread-2 is stop
Thread-1 is stop
從結果可以看出,多個例項的執行緒同時進入了同步的非靜態方法。
Demo3:多個例項的執行緒進入靜態的同步方法。
package SynchronizedTest;
/**
* Created by carrot on 16/8/31.
*/
public class SyncFunc {
public static synchronized void func1() {
System.out.println(Thread.currentThread().getName() + " is running");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " is stop");
}
public static void main(String[] args) {
NewThread newThread1 = new NewThread();
NewThread newThread2 = new NewThread();
NewThread newThread3 = new NewThread();
newThread1.start();
newThread2.start();
newThread3.start();
}
}
class NewThread extends Thread {
SyncFunc syncFunc = new SyncFunc();
@Override
public void run() {
syncFunc.func1();
}
}
結果:
Thread-0 is running
Thread-0 is stop
Thread-2 is running
Thread-2 is stop
Thread-1 is running
Thread-1 is stop
從結果可以看出,對於同一個物件的多個例項,在進入靜態的同步方法時,一次只能有一個類例項進入。