Java synchronized到底鎖住的是什麼?

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

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

使用:synchronized鎖住的是括號裏的對象,而不是代碼。對於非static的synchronized方法,鎖的就是對象自己也就是this。測試

經過如下兩個案例說明: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();
        }
    }

}


執行結果:

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

分析上述執行結果可知:線程

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

 

所以,能夠修改代碼,讓三個線程使用同一個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 }

 運行結果:

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

分析上述結果:因爲每次新線程啓動,使用的同一對象sync,所以synchronized生效了。io

 

固然,更經常使用的方法是:使用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方法也至關於全局鎖,至關於鎖住了代碼段。

相關文章
相關標籤/搜索