普通方法上:
synchronized 在普通方法上爲對象鎖,不通對象調用時不會阻塞,相同對象調用時爲同步阻塞。
示例如下:
public class Task { public synchronized void funA(){ System.out.println("======== start running funA ... ========"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("======== end running funA ... ========"); } public synchronized void funB(){ System.out.println("======== start running funB ... ======== "); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("======== end running funB ... ======== "); } public static void main(String[] args) { // 三個線程分別是同的對象調用funA -- 不會阻塞 for (int i=0; i<3;i++){ new Thread(() -> new Task().funA()).start(); } // 三個線程分別是同的對象調用funB -- 不會阻塞 for (int i=0; i<3;i++){ new Thread(() -> new Task().funB()).start(); } // 三個線程同的對象調用funA -- 同步阻塞 Task task = new Task(); for (int i=0; i<3;i++){ new Thread(() -> task.funA()).start(); } // 三個線程同的對象調用funB -- 同步阻塞 for (int i=0; i<3;i++){ new Thread(() -> task.funB()).start(); } } }
代碼塊:
synchronized(Task.class)爲類鎖,則無論是都相同對象調用都爲同步阻塞.。
synchronized(this)爲對象鎖,不通對象調用時不會阻塞,相同對象調用時爲同步阻塞。
public class Task { public void funC(){ synchronized(Task.class) { System.out.println("======== start running funC ... ========"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("======== end running funC ... ========"); } } public void funD(){ synchronized(this) { System.out.println("======== start running funD ... ========"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("======== end running funD ... ========"); } } public static void main(String[] args) { // 三個線程分別是同的對象調用funC -- 同步阻塞 for (int i=0; i<3;i++){ new Thread(() -> new Task().funC()).start(); } // 三個線程分別是同的對象調用funD -- 不會阻塞 for (int i=0; i<3;i++){ new Thread(() -> new Task().funD()).start(); } } }
靜態方法上:
synchronized在靜態方法上爲對象鎖,無論是否同一對象都爲同步阻塞
public class Task { public static synchronized void funE(){ System.out.println("======== start running funE ... ========"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("======== end running funE ... ========"); } public static synchronized void funF(){ System.out.println("======== start running funF ... ======== "); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("======== end running funF ... ======== "); } public static void main(String[] args) { // 三個線程分別是同的對象調用funA -- 同步阻塞 for (int i=0; i<3;i++){ new Thread(() -> new Task().funE()).start(); } // 三個線程分別是同的對象調用funD -- 同步阻塞 Task task = new Task(); for (int i=0; i<3;i++){ new Thread(() -> task.funF()).start(); } } }
總結
對象鎖:同一個對象下是同步阻塞的,不同對象之間非阻塞的。
類鎖:無論是否爲相同對象均爲同步阻塞。
同一個類多個方法被synchronized修飾/代碼塊/靜態方法,則在各個方法之間也是同步阻塞的。