synchronized,是Java語言的關鍵字,讀['siŋkrənaizd],當它用來修飾一個方法或者一個代碼塊的時候,可以保證在同一時刻最多隻有一個線程執行該段代碼。編程
線程的同步是爲了防止多個線程訪問一個數據對象時,對數據形成的破壞。爲確保共享變量不會出現併發問題,一般會對修改共享變量的代碼塊用synchronized
加鎖,確保同一時刻只有一個線程在修改共享變量,從而避免併發問題。因此須要緊緊記住「共享」這兩個字,只有共享資源的讀寫訪問才須要同步化,若是不是共享資源,那麼就沒有同步的必要。安全
修飾實例方法 > 多個線程訪問同一個實例的加鎖方法時,會出現鎖的競爭多線程
修飾靜態方法 > 多個線程訪問類的加鎖方法時,會出現鎖的競爭併發
修飾代碼塊 > 多線程訪問到同一個代碼塊時,會出現競爭的問題ide
synchronized能夠用來修飾方法或代碼塊,咱們能夠把獲取的同步鎖歸爲如下3種:學習
對這3種不一樣的鎖,使用相互之間不受影響,對於同一種鎖,會出現鎖的競態條件。測試
對於1.實例對象鎖的使用:this
對於2.類對象鎖的使用:spa
對於3.同步塊非當前實例對象鎖的使用:.net
3.測試case代碼
package com.test.synchroniz; public class Service { public Service(){ System.out.println("當前線程:" + Thread.currentThread().getName() + " 構造方法"); } static{ System.out.println("當前線程:" + Thread.currentThread().getName() + " 靜態代碼塊"); } private Object object1 = new Object(); private Object object2 = new Object(); synchronized public static void printA(){ try{ System.out.println("當前線程:" + Thread.currentThread().getName() + Thread.currentThread().getId() +"在 " + System.currentTimeMillis() + " 進入方法A"); Thread.sleep(3000); System.out.println("當前線程:" + Thread.currentThread().getName() + Thread.currentThread().getId() +"在 " + System.currentTimeMillis() + " 退出方法A"); }catch(Exception e){ System.out.println(e); } } synchronized public void printB(){ try{ System.out.println("當前線程:" + Thread.currentThread().getName() + Thread.currentThread().getId() +"在 " + System.currentTimeMillis() + " 進入方法B"); Thread.sleep(3000); System.out.println("當前線程:" + Thread.currentThread().getName() + Thread.currentThread().getId() +"在 " + System.currentTimeMillis() + " 退出方法B"); }catch(Exception e){ System.out.println(e); } } public void printC(){ System.out.println("當前線程:" + Thread.currentThread().getName() + Thread.currentThread().getId() +"在 " + System.currentTimeMillis() + " 進入方法C"); try{ synchronized(object1){ System.out.println("當前線程:" + Thread.currentThread().getName() + Thread.currentThread().getId() +"在 " + System.currentTimeMillis() + "進入方法C--synchronized{X}"); Thread.sleep(3000); System.out.println("當前線程:" + Thread.currentThread().getName() + Thread.currentThread().getId() +"在 " + System.currentTimeMillis() + " 退出方法C-synchronized{X}"); } System.out.println("當前線程:" + Thread.currentThread().getName() + Thread.currentThread().getId() +"在 " + System.currentTimeMillis() + " 退出方法C"); }catch(Exception e){ System.out.println(e); } } public void printD(){ System.out.println("當前線程:" + Thread.currentThread().getName() + Thread.currentThread().getId() +"在 " + System.currentTimeMillis() + " 進入方法D"); try{ synchronized(object2){ System.out.println("當前線程:" + Thread.currentThread().getName() + Thread.currentThread().getId() +"在 " + System.currentTimeMillis() + "進入方法D--synchronized{X}"); Thread.sleep(3000); System.out.println("當前線程:" + Thread.currentThread().getName() + Thread.currentThread().getId() +"在 " + System.currentTimeMillis() + " 退出方法D-synchronized{X}"); } System.out.println("當前線程:" + Thread.currentThread().getName() + Thread.currentThread().getId() +"在 " + System.currentTimeMillis() + " 退出方法D"); }catch(Exception e){ System.out.println(e); } } public void printE(){ System.out.println("當前線程:" + Thread.currentThread().getName() + Thread.currentThread().getId() +"在 " + System.currentTimeMillis() + " 進入方法E"); try{ synchronized(this){ System.out.println("當前線程:" + Thread.currentThread().getName() + Thread.currentThread().getId() +"在 " + System.currentTimeMillis() + " 進入方法E--synchronized{this}"); Thread.sleep(3000); System.out.println("當前線程:" + Thread.currentThread().getName() + Thread.currentThread().getId() +"在 " + System.currentTimeMillis() + " 退出方法E-synchronized{this}"); } System.out.println("當前線程:" + Thread.currentThread().getName() + Thread.currentThread().getId() +"在 " + System.currentTimeMillis() + " 退出方法E"); }catch(Exception e){ System.out.println(e); } } public static void printF(){ System.out.println("當前線程:" + Thread.currentThread().getName() + Thread.currentThread().getId() +"在 " + System.currentTimeMillis() + " 進入方法E"); try{ synchronized(Service.class){ System.out.println("當前線程:" + Thread.currentThread().getName() + Thread.currentThread().getId() +"在 " + System.currentTimeMillis() + " 進入方法F--synchronized{class}"); Thread.sleep(3000); System.out.println("當前線程:" + Thread.currentThread().getName() + Thread.currentThread().getId() +"在 " + System.currentTimeMillis() + " 退出方法F-synchronized{class}"); } System.out.println("當前線程:" + Thread.currentThread().getName() + Thread.currentThread().getId() +"在 " + System.currentTimeMillis() + " 退出方法F"); }catch(Exception e){ System.out.println(e); } } public void printG(){ System.out.println("當前線程:" + Thread.currentThread().getName() + Thread.currentThread().getId() +"在 " + System.currentTimeMillis() + " 進入方法G"); try{ synchronized(Service.class){ System.out.println("當前線程:" + Thread.currentThread().getName() + Thread.currentThread().getId() +"在 " + System.currentTimeMillis() + " 進入方法G--synchronized{class}"); Thread.sleep(3000); System.out.println("當前線程:" + Thread.currentThread().getName() + Thread.currentThread().getId() +"在 " + System.currentTimeMillis() + " 退出方法G-synchronized{class}"); } System.out.println("當前線程:" + Thread.currentThread().getName() + Thread.currentThread().getId() +"在 " + System.currentTimeMillis() + " 退出方法G"); }catch(Exception e){ System.out.println(e); } } }
package com.test.synchroniz; /** * 0.synchronized同步方法、synchronized靜態同步方法分別是用到的是實例鎖,類鎖,一個線程獲取到synchronized同步方法的鎖時, * 另外一線程依然能夠進入synchronized靜態同步方法(實例鎖,類鎖二者不一樣,相互不影響 * ) * 1.synchronized同步方法,synchronized(this)都是對象鎖,對於其餘線程調用synchronized同步方法,synchronized(this)呈阻塞狀態 </br> * 2.同一時間同一線程只有一個線程獲取對象鎖執行 </br> * * 1.synchronized(非this)對象鎖,對於非this若是是同一對象,兩個線程同時只有一個能夠獲取該鎖 </br> * 2.對象鎖(synchronized同步方法 或 synchronized(this))、synchronized(非this)對象鎖 兩個線程同時執行,均可得到各自的鎖 </br> * * 1.synchronized修飾static方法與synchronized(X.class)做用同樣 * * @author fugaoyang * */ public class TestRun { public static void main(String[] args) throws Exception { Service service = new Service(); Thread threadA = new Thread("A"){ @Override public void run(){ service.printA(); } }; Thread threadB = new Thread("B"){ @Override public void run(){ service.printB(); } }; Thread threadC = new Thread("C"){ @Override public void run(){ service.printC(); } }; Thread threadD = new Thread("D"){ @Override public void run(){ service.printD(); } }; Thread threadE = new Thread("E"){ @Override public void run(){ service.printE(); } }; Thread threadF = new Thread("F"){ @Override public void run(){ service.printF(); } }; Thread threadG = new Thread("G"){ @Override public void run(){ service.printG(); } }; threadA.start(); //threadB.start(); //threadC.start(); //threadD.start(); //threadE.start(); threadF.start(); threadG.start(); threadA.join(); threadF.join(); threadG.join(); } }