synchronized之鎖淺析

前言

廢話少說,主要是弄清楚概念上的東西,方便在寫程序中實際運用。

鎖的分類

對象鎖:synchronized修飾具體的類的實例對象,或者修飾類的一個方法
方法鎖:synchronized修飾類的一個方法
類鎖:synchronized修飾一個類的靜態方法,或者修飾諸如(Object.class)

具體的代碼

對象鎖

修飾具體的類的實例對象

public class Test {
    public void method(){
        synchronized(this){
            System.out.println("我是對象鎖");
        }
    }
}

也可以這麼寫

public class Test{
    private Test test=new Test();
    public void method(){
        synchronized(test){
            System.out.println("我是對象鎖");
        }
    }
}

修飾類的一個方法時

public class Test{
    public synchronized void method(){
        System.out.println("我是對象鎖也是方法鎖");
    }
}

方法鎖

上面已經提到了,如下

public class Test{
    public synchronized void method(){
        System.out.println("我是方法鎖也是對象鎖");
    }
}

類鎖

public class Test{
    public void method(){
        synchronized(Test.class){
            System.out.println("我是類鎖");
        }
    }
}

修飾類的靜態方法時

public class Test{
    public synchronized static void method(){
        System.out.println("我是類鎖");
    }
}

至於爲什麼鎖靜態方法就是類鎖,稍作解釋:
因爲一個方法被定義爲靜態之後,那麼該方法就屬於這個類,而不是類的實例,在內存中也只有一份,我把這個僅有的一份鎖住了,其它要調用的只能去請求鎖,從而實現鎖類。

我之前的小疑問

關於鎖這裏,我之前一直有個疑問:爲什麼一般的操作都是鎖類,鎖實例對象,或者鎖方法,爲啥不鎖類的成員變量呢?

我現在的理解是:既然我鎖成員變量,肯定希望這個成員變量不被兩個線程同時更改造成不同步的問題,但是這個問題完全可以由鎖對象實例來解決,而且鎖對象實例範圍更加大一點,這個對象實例的所有成員變量的操作都是同步的,其實鎖類也可以,只不過鎖類只能鎖靜態成員變量。

關於這個小疑問,可能我的理解有失偏頗,還望不吝賜教!

後來補充:關於上面這個疑問,看到有的文章解釋的比較詳細,給出的理由是:實例變量和類變量本身就不持有鎖,所以無法對其進行加鎖。

然後關於這三種鎖的作用,方法鎖我=就不用贅述了,類鎖和對象鎖的作用:
對象鎖是用來控制實例方法之間的同步,類鎖是用來控制靜態方法(或靜態變量互斥體)之間的同步
方法鎖(非靜態方法)其實也可以理解爲對象鎖,因爲要訪問synchronized修飾的方法,要獲得對象鎖才行

一些易錯的地方

關於對象鎖這裏,如果是鎖的兩個不同的類對象實例,二者是不會同步的,因爲我們所說的對象鎖,只是針對同一個實例對象,如果是兩個不同的實例對象,不會具有競爭關係。說簡單點就是,多個對象會有多個鎖,互不干擾。

結語

暫時到這,實際使用如果有什麼問題,再拿來這裏結合分析。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章