Java中的對象級別鎖和類級別鎖

在Java中,synchronized代碼塊一次只能由一個線程執(zhí)行。此外,java支持并發(fā)執(zhí)行多個線程。這可能導(dǎo)致兩個或多個線程同時訪問相同的字段或?qū)ο蟆?/p>

同步是保持執(zhí)行中的所有并發(fā)線程同步的過程。同步避免了由于共享內(nèi)存視圖不一致而導(dǎo)致的內(nèi)存一致性錯誤。當(dāng)一個方法被聲明為同步的;線程持有該方法的對象的監(jiān)聽或鎖對象。如果另一個線程正在執(zhí)行同步方法,那么您的線程將被阻塞,直到該線程釋放監(jiān)聽為止。

請注意,我們可以在類中對已定義的方法或塊使用synchronized關(guān)鍵字。synchronized關(guān)鍵字不能與類定義中的變量或?qū)傩砸黄鹗褂谩?/p>

1. Java中的對象級鎖定

對象級鎖是一種機(jī)制,當(dāng)我們想要同步一個非靜態(tài)方法或非靜態(tài)代碼塊時,這樣只有一個線程能夠在類的給定實例上執(zhí)行代碼塊。應(yīng)該始終這樣做,以使實例級數(shù)據(jù)線程安全。

對象級鎖定可以如下所示:

public class DemoClass
{
    public synchronized void demoMethod(){}
}
 
or
 
public class DemoClass
{
    public void demoMethod(){
        synchronized (this)
        {
            //other thread safe code
        }
    }
}
 
or
 
public class DemoClass
{
    private final Object lock = new Object();
    public void demoMethod(){
        synchronized (lock)
        {
            //other thread safe code
        }
    }
}

2. Java中的類級別鎖

類級鎖防止多個線程在運行時的任何可用類實例中進(jìn)入同步塊。這意味著如果在運行時有100個DemoClass實例,那么每次只有一個線程能夠在任何一個實例中執(zhí)行demoMethod(),而其他所有實例對于其他線程來講都是被鎖定的。

應(yīng)該始終執(zhí)行類級鎖定,以使靜態(tài)數(shù)據(jù)線程安全。正如我們所知道的,static關(guān)鍵字將方法的數(shù)據(jù)關(guān)聯(lián)到類級別,因此在靜態(tài)字段或方法上使用鎖定將其關(guān)聯(lián)到類級別。

參照下面類級別鎖定的例子:

public class DemoClass
{
    //Method is static
    public synchronized static void demoMethod(){
 
    }
}
 
or
 
public class DemoClass
{
    public void demoMethod()
    {
        //Acquire lock on .class reference
        synchronized (DemoClass.class)
        {
            //other thread safe code
        }
    }
}
 
or
 
public class DemoClass
{
    private final static Object lock = new Object();
 
    public void demoMethod()
    {
        //Lock object is static
        synchronized (lock)
        {
            //other thread safe code
        }
    }
}

3. 對象級別鎖定與類級別鎖定 - 重要說明

  1. Java中的同步確保沒有兩個線程可以同時或并發(fā)地執(zhí)行需要相同鎖的同步方法。
  2. synchronized關(guān)鍵字只能用于方法和代碼塊。這些方法或塊可以是靜態(tài)的,也可以是非靜態(tài)的。
  3. 每當(dāng)線程進(jìn)入Javasynchronized方法或塊時,它就獲得一個鎖;每當(dāng)線程離開synchronized方法或塊時,它就釋放鎖。即使線程在完成后或由于任何錯誤或異常離開synchronized方法,也會釋放鎖。
  4. Java synchronized關(guān)鍵字本質(zhì)上是可重入的,這意味著如果一個synchronized方法調(diào)用另一個需要相同鎖的synchronized方法,那么持有鎖的當(dāng)前線程可以在不獲取鎖的情況下進(jìn)入該方法。
  5. 如果同步塊中使用的對象為空,Java同步將拋出NullPointerException。例如,在上面的代碼示例中,如果鎖初始化為nullsynchronized (lock)將拋出NullPointerException。
  6. Java中的同步方法會給應(yīng)用程序帶來性能損失。所以在絕對需要的時候使用同步。另外,考慮使用同步代碼塊只同步代碼的關(guān)鍵部分。
  7. 靜態(tài)同步和非靜態(tài)同步方法可能同時或并發(fā)地運行,因為它們鎖定不同的對象。
  8. 根據(jù)Java語言規(guī)范,不能在構(gòu)造函數(shù)中使用synchronized關(guān)鍵字。這是非法的,會導(dǎo)致編譯錯誤。
  9. 不要在Java同步塊的非final字段上同步。因為非final字段的引用可能隨時改變,不同的線程可能在不同的對象上同步,即根本沒有同步。
  10. 不要使用String文字,因為它們可能在應(yīng)用程序的其他地方被引用,并可能導(dǎo)致死鎖。使用new關(guān)鍵字創(chuàng)建的String對象可以安全地使用。但是最好是,創(chuàng)建一個新的私有范圍的對象實例,或者鎖定我們想要保護(hù)的共享變量本身。

參考資料:

Object level lock vs Class level lock in Java

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 整理來自互聯(lián)網(wǎng) 1,JDK:Java Development Kit,java的開發(fā)和運行環(huán)境,java的開發(fā)工具...
    Ncompass閱讀 1,624評論 0 6
  • 進(jìn)程和線程 進(jìn)程 所有運行中的任務(wù)通常對應(yīng)一個進(jìn)程,當(dāng)一個程序進(jìn)入內(nèi)存運行時,即變成一個進(jìn)程.進(jìn)程是處于運行過程中...
    勝浩_ae28閱讀 5,260評論 0 23
  • 一:java概述: 1,JDK:Java Development Kit,java的開發(fā)和運行環(huán)境,java的開發(fā)...
    慕容小偉閱讀 1,956評論 0 10
  • 一:java概述:1,JDK:Java Development Kit,java的開發(fā)和運行環(huán)境,java的開發(fā)工...
    ZaneInTheSun閱讀 2,822評論 0 11
  • 歷史曾有煮酒論英雄,今日我來論生活。思修課上,老師講了三個農(nóng)民工的故事。他們?nèi)齻€人以不同的態(tài)度面對著工作,生...
    暗里閱讀 615評論 0 2

友情鏈接更多精彩內(nèi)容