Java synchronized到底鎖住的是什么?


使用環境:多線程java程序中。

作用:在多線程的環境下,控制synchronized代碼段不被多個線程同時執行。synchronized既可以加在一段代碼上,也可以加在方法上。

使用:synchronized鎖住的是括號里的對象,而不是代碼。對於非static的synchronized方法,鎖的就是對象本身也就是this。

通過以下兩個案例說明:

//包含了synchronized 方法的類
public class SynchronizedMethod {
    public synchronized void test()
    {
        System.out.println("線程開始..");
        try {
            Thread.sleep(2000);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("線程結束..");
    }
}

//測試類
public class MyThread extends Thread{
    public void run(){
        SynchronizedMethod clazz = new SynchronizedMethod();
        clazz.test();
    }
    
    public static void main(String[] args) {
        for(int i=0;i<3;i++)
        {
            Thread thread = new MyThread();
            thread.start();
        }
    }

}


執行結果:

線程開始..
線程開始..
線程開始..
線程結束..
線程結束..
線程結束..

分析上述執行結果可知:

  當main方法執行時,分別創建了三個MyThread對象,而這三個對象又各自創建了獨立的 SynchronizedMethred類,雖然使用了test方法使用了synchronized方法修飾,但是synchronized鎖住的是三個獨立的對象,因為三個對象各自分別執行了test方法。

 

因此,可以修改代碼,讓三個線程使用同一個SynchronizedMethod對象:

 

 1 //修改測試類代碼如下,使用同一對象調用test方法
 2 
 3 public class MyThread extends Thread{
 4 
 5     /**
 6      * Author:LearnAndGet
 7      */
 8     private SynchronizedMethod sync;
 9     public MyThread(SynchronizedMethod sync)
10     {
11         this.sync = sync;
12     }
13     
14     public void run(){
15         sync.test();
16     }
17 
18     
19     public static void main(String[] args) {
20         SynchronizedMethod sync = new SynchronizedMethod();
21         for(int i=0;i<3;i++)
22         {
23             MyThread thread = new MyThread(sync);
24             thread.start();
25         }
26     }
27 }

 運行結果:

線程開始..
線程結束..
線程開始..
線程結束..
線程開始..
線程結束..

分析上述結果:由於每次新線程啟動,使用的同一對象sync,因此synchronized生效了。

 

當然,更常用的方法是:使用schronized鎖住這個類對應的Class對象:

public class SynchronizedMethod {
    public void test()
    {
        //將代碼塊使用synchronized鎖住
        synchronized(SynchronizedMethod.class)
        {
            System.out.println("線程開始..");
            try {
                Thread.sleep(2000);
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println("線程結束..");
        }
    }
}

使用上述代碼后,即使每次創建不同的SynchronizedMethod對象,執行其test方法時,因為synchronized鎖住了SynchronizedMethod類對應的class對象,所以每次只能有一個SynchronizedMethod的對象獲取鎖,直到該鎖獲得釋放,其他SynchronizedMethod對象都無法執行其方法。

上述代碼中,通過使用 synchronized(SynchronizedMethod.class)實現了全局鎖的效果

除此之外,使用 static synchronized一起修飾方法時,static方法可以直接類名加方法名調用,方法中無法使用this,所以它鎖的不是this,而是類的Class對象,所以,static synchronized方法也相當於全局鎖,相當於鎖住了代碼段。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM