整理synchronized、static synchronized以及synchronized(obj)區別
阿新 • • 發佈:2021-02-09
技術標籤:java
文章目錄
對java中synchronized應用場景做下整理,方面自己以後檢視
synchronized使用者髮結論:
- 1.
public synchronized void syncMethod(String flag){}
鎖當前物件this,等價程式碼塊鎖synchronized (this){}
- 1.1 同一個例項物件同一個時刻只能有一個在呼叫,不同例項可以同時呼叫
- 2.
public static synchronized void syncStaticMethod{}
是鎖當前對應class物件,等價程式碼塊鎖synchronized (SyncServiceTest.class){}
- 2.1 鎖物件為SyncServiceTest.class與呼叫方法的物件無關,因此同一個時刻不管是否為同一個物件呼叫都只有一個在執行
- 3.
synchronized (obj){}
,鎖obj物件 - 4.注意上面三種鎖的物件都是不同的,分別對應當前物件this、當前類物件SyncServiceTest.class以及obj物件 因此相互之間呼叫不會有影響
- 5.synchronized方法、程式碼塊相互之間是否有影響關鍵是看鎖的是否為同一個物件
demo測試用例
public class SyncServiceTest { private Object lockObj = new Object(); public void syncLockObj(String flag) { synchronized (lockObj) { print(flag); } } public synchronized void syncMethod(String flag) { //等價synchronized (this){} print(flag); } public void syncCodeBlockByThis(String flag) { synchronized (this) { print(flag); } } public static synchronized void syncStaticMethod(String flag) { /** *1.static synchronized是鎖對應class,與synchronized (SyncServiceTest.class)寫法等價 * *2. synchronized (obj){},鎖obj物件 * *3. public synchronized void syncMethod(String flag){} 鎖當前物件this,等價synchronized (this){} * * - 注意上面三種鎖的物件都是不同的,分別對應SyncServiceTest.class,obj,this 因此相互之間呼叫不會有影響 * * - synchronized方法、程式碼塊相互之間是否有影響關鍵是看鎖的是否為同一個物件 * */ print(flag); } public void syncCodeBlockByClass(String flag) { //需要驗證 對應統一 object synchronized 修改的程式碼同一個時間點只能有一個在訪問 synchronized (SyncServiceTest.class) { print(flag); } } public static void print(String msg) { for (int i = 0; i < 3; i++) { //Thread.currentThread().getStackTrace()[2]獲取上一級呼叫的方法 //Thread.currentThread().getStackTrace()[1]獲取當前方法(即print) String log = String.format("method=%s,thread=%s,flag=%s,i=%s", Thread.currentThread().getStackTrace()[2].getMethodName(), Thread.currentThread().getName(), msg, i); System.out.println(log); randomSleep(500); } } /** * @param timer 毫秒 * @return */ private static void randomSleep(int timer) { long sleepTimer = Math.round(Math.random() * timer); try { Thread.sleep(sleepTimer); } catch (InterruptedException e) { e.printStackTrace(); } } //--------------------test method分割線--------------- public void testInvokeTwoSyncObj() { System.out.println("測試呼叫synchronized(obj)"); //結論同一個時刻之後有一個方法獲取到成員變數(lockObj)的鎖 SyncServiceTest service = new SyncServiceTest(); Thread t1 = new Thread(() -> { service.syncLockObj("lock1"); }); Thread t2 = new Thread(() -> { service.syncLockObj("lock2"); }); t1.start(); t2.start(); } public void testInvokeSyncObjAndSyncMethod() { System.out.println("測試呼叫synchronized(obj)與public synchronized void syncMethod(String flag){}"); //成員變數(lockObj)的鎖物件與普通方法鎖物件不是同一個,因此不會相互影響 //普通方法syncMethod()鎖物件為當前物件this,成員變數鎖物件是lockObj本身 SyncServiceTest service = new SyncServiceTest(); Thread t1 = new Thread(() -> { service.syncLockObj("lock1"); }); Thread t2 = new Thread(() -> { service.syncMethod("lock2"); }); t1.start(); t2.start(); } public void testInvokeTwoSyncMethod() { System.out.println("測試呼叫public synchronized void syncMethod(String flag){}"); SyncServiceTest service = new SyncServiceTest(); Thread t1 = new Thread(() -> { service.syncMethod("lock1"); }); Thread t2 = new Thread(() -> { service.syncMethod("lock2"); }); t1.start(); t2.start(); } public void testTwoDemoInvokeSyncMethod() { System.out.println("測試呼叫public void syncMethod(){}"); Thread t1 = new Thread(() -> { new SyncServiceTest().syncMethod("lock1"); }); Thread t2 = new Thread(() -> { new SyncServiceTest().syncMethod("lock2"); }); t1.start(); t2.start(); } public void testSyncStaticMethod() { System.out.println("測試呼叫public synchronized void syncMethod(){}"); Thread t1 = new Thread(() -> { new SyncServiceTest().syncStaticMethod("lock1"); }); Thread t2 = new Thread(() -> { new SyncServiceTest().syncStaticMethod("lock2"); }); t1.start(); t2.start(); } public void testSyncStaticMethodAndLockClass() { System.out.println("測試呼叫public static synchronized void syncMethod(){}與synchronized(SyncServiceTest.class)"); Thread t1 = new Thread(() -> { new SyncServiceTest().syncStaticMethod("lock1"); }); Thread t2 = new Thread(() -> { new SyncServiceTest().syncCodeBlockByClass("lock2"); }); t1.start(); t2.start(); } public static void main(String[] args) { SyncServiceTest t = new SyncServiceTest(); // t.testInvokeTwoSyncObj(); // t.testInvokeSyncObjAndSyncMethod(); // t.testInvokeTwoSyncMethod(); // t.testTwoDemoInvokeSyncMethod(); t.testSyncStaticMethodAndLockClass(); } }