深入理解Java中的同步靜態方法和synchronized(class)程式碼塊的類鎖 深入理解Java併發synchronized同步化的程式碼塊不是this物件時的操作
一.回顧學習內容
在前面幾篇部落格中我我們已經理解了synchronized物件鎖、物件鎖的重入、synchronized方法塊、synchronized非本物件的程式碼塊,
連結:https://www.cnblogs.com/SAM-CJM/category/1314992.html
我們來總結一下,上面幾篇講到內容:
1.建立執行緒類的兩個方式:繼承Thread類和實現Runable介面。
2.瞭解了Thread類的幾個基本構造器。
3.啟動多執行緒時要使用start方法,不要直接呼叫run方法。
4.幾個多執行緒中常用的方法。
5.解決一個共享資源被多個執行緒呼叫時採用了synchronized同步化一個物件的方法。
6.一個執行緒可以在進入一個同步化的方法時再去進入這個物件的另外一個同步化方法,這個就是物件鎖的重入。
7.為了提高程式的執行效率,我們可以不去直接同步一個方法,直接同步這個方法中有關共享資料的部分,其他部分就是非同步執行的。
8.上一篇講到了使用synchronized同步一個不是本物件的程式碼塊
二.匯入問題
我們到現在使用的synchronized方法同步的都是非靜態的方法也就是給一個物件上來一把物件鎖,那麼我們去給一個靜態方法會有什麼效果呢?
三.同步將靜態方法、同步類資源
其實在Java中給一個靜態方法上鎖就是給一個類上鎖,因為類也可以是一個共享資源。
程式碼如下:
public class SynClass {//這個類為共享資源 //這個靜態方法沒有被同步 public static void fun() throws InterruptedException { System.out.println("**************begin**************"); Thread.sleep(4000); System.out.println("**************end**************"); } public static void main(String[] args) { ThreadA t1=new ThreadA(); ThreadA t2=new ThreadA(); t1.start(); t2.start(); } } class ThreadA extends Thread {//建立執行緒 @Override public void run(){ try { SynClass.fun();//呼叫靜態方法 } catch (InterruptedException e) { e.printStackTrace(); } } }
結果就是出現了執行緒不同步:
修改程式碼如下:
//這個靜態方法被同步 synchronized public static void fun() throws InterruptedException { System.out.println("**************begin**************"); Thread.sleep(4000); System.out.println("**************end**************"); }
結果被同步:
說明類也可以是共享資源,同步靜態方法也是在同步類資源。
四.類鎖和物件鎖的認識
假如我們有兩把鎖一把是類鎖,一把是物件鎖,那麼會出現什麼情況呢?
程式碼如下:
public class SynClassObject { //建立一個同步的靜態的方法 public synchronized static void static_fun(){//類鎖 System.out.println("**********靜態方法begin*********"); System.out.println("**********靜態方法end***********"); } //建立同步的非靜態方法 public synchronized void notStatic_fun(){//物件鎖 System.out.println("***********非靜態方法begin*************"); System.out.println("***********非靜態方法end***************"); } public static void main(String[] args) { new SynClassObjectThread1().start(); new SynClassObjectThread2().start(); } } class SynClassObjectThread1 extends Thread{//這個執行緒類呼叫的是同步化的靜態方法 @Override public void run(){ SynClassObject.static_fun(); } } class SynClassObjectThread2 extends Thread{//這個執行緒類是呼叫非靜態方法 private SynClassObject synClassObject =new SynClassObject(); @Override public void run(){ synClassObject.notStatic_fun(); } }
結果入下: 明顯他是不同步的,因為物件鎖和類鎖是兩把不同的鎖。
同樣的道理對於同步靜態程式碼塊,也是對類資源實現了一個同步。
***************************往期部落格糾錯******************************
在此要感謝@使用者註冊了一次老哥,幫助指出了深入理解Java併發synchronized同步化的程式碼塊不是this物件時的操作中的錯誤,這一篇文章只是為了說明synchronized關鍵字同步的是物件而不是方法,我舉的列子的確有失偏頗,本人水平有限,如有錯誤請大家斧正。
************************************************************************