最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

淺談Java的Synchronized鎖原理和優(yōu)化

 更新時(shí)間:2023年05月12日 10:47:39   作者:Java筆記蝦  
這篇文章主要介紹了Java的Synchronized鎖原理和優(yōu)化,synchronized的作用是保證在同一時(shí)刻, 被修飾的代碼塊或方法只會(huì)有一個(gè)線程執(zhí)行,以達(dá)到保證并發(fā)安全的效果,需要的朋友可以參考下

一、synchronized介紹

synchronized中文意思是同步,也稱之為”同步鎖“。

synchronized的作用是保證在同一時(shí)刻, 被修飾的代碼塊或方法只會(huì)有一個(gè)線程執(zhí)行,以達(dá)到保證并發(fā)安全的效果。

synchronized是Java中解決并發(fā)問(wèn)題的一種最常用的方法,也是最簡(jiǎn)單的一種方法。

在JDK1.5之前synchronized是一個(gè)重量級(jí)鎖,相對(duì)于j.u.c.Lock,它會(huì)顯得那么笨重,隨著Javs SE 1.6對(duì)synchronized進(jìn)行的各種優(yōu)化后,synchronized并不會(huì)顯得那么重了。

synchronized的作用主要有三個(gè):

  • 原子性: 確保線程互斥地訪問(wèn)同步代碼;
  • 可見(jiàn)性: 保證共享變量的修改能夠及時(shí)可見(jiàn),其實(shí)是通過(guò)Java內(nèi)存模型中的 “ 對(duì)一個(gè)變量unlock操作之前,必須要同步到主內(nèi)存中;如果對(duì)一個(gè)變量進(jìn)行l(wèi)ock操作,則將會(huì)清空工作內(nèi)存中此變量的值,在執(zhí)行引擎使用此變量前,需要重新從主內(nèi)存中l(wèi)oad操作或assign操作初始化變量值 ” 來(lái)保證的;
  • 有序性: 有效解決重排序問(wèn)題,即 “一個(gè)unlock操作先行發(fā)生(happen-before)于后面對(duì)同一個(gè)鎖的lock操作”;

二、synchronized的使用

synchronized的3種使用方式:

  • 修飾實(shí)例方法: 作用于當(dāng)前實(shí)例加鎖
  • 修飾靜態(tài)方法: 作用于當(dāng)前類(lèi)對(duì)象加鎖
  • 修飾代碼塊: 指定加鎖對(duì)象,對(duì)給定對(duì)象加鎖

1.修飾方法

Synchronized修飾一個(gè)方法很簡(jiǎn)單,就是在方法的前面加synchronizedsynchronized修飾方法和修飾一個(gè)代碼塊類(lèi)似,只是作用范圍不一樣,修飾代碼塊是大括號(hào)括起來(lái)的范圍,而修飾方法范圍是整個(gè)函數(shù)。

  • 方法一:修飾的是一個(gè)方法
public synchronized void method()
{
   // todo
}
  • 方法二:修飾的是一個(gè)代碼塊
public void method()
{
   synchronized(this) {
      // todo
   }
}

方法一與方法二是等價(jià)的,都是鎖定了整個(gè)方法時(shí)的內(nèi)容。

synchronized關(guān)鍵字不能繼承。雖然可以使用synchronized來(lái)定義方法,但synchronized并不屬于方法定義的一部分,因此,synchronized關(guān)鍵字不能被繼承。

  • 在子類(lèi)方法中加上synchronized關(guān)鍵字
class Parent {
   public synchronized void method() { }
}
class Child extends Parent {
   public synchronized void method() { }
}
  • 在子類(lèi)方法中調(diào)用父類(lèi)的同步方法
class Parent {
   public synchronized void method() {   }
}
class Child extends Parent {
   public void method() { super.method();   }
}

注意:

  • 在定義接口方法時(shí)不能使用synchronized關(guān)鍵字。
  • 構(gòu)造方法不能使用synchronized關(guān)鍵字,但可以使用synchronized代碼塊來(lái)進(jìn)行同步。

當(dāng)有一個(gè)明確的對(duì)象作為鎖時(shí),就可以用類(lèi)似下面這樣的方式寫(xiě)程序:

public void method3(SomeObject obj)
{
   //obj 鎖定的對(duì)象
   synchronized(obj)
   {
      // todo
   }
}

當(dāng)沒(méi)有明確的對(duì)象作為鎖,只是想讓一段代碼同步時(shí),可以創(chuàng)建一個(gè)特殊的對(duì)象來(lái)充當(dāng)鎖:

class Test implements Runnable
{
   private byte[] lock = new byte[0];  // 特殊的instance變量
   public void method()
   {
      synchronized(lock) {
         // todo 同步代碼塊
      }
   }
   public void run() {
   }
}
  • 2.修飾一個(gè)靜態(tài)方法

synchronized也可修飾一個(gè)靜態(tài)方法,用法如下:

public synchronized static void method() {
   // todo
}
  • 3.修飾一個(gè)類(lèi)

Synchronized還可作用于一個(gè)類(lèi),用法如下:

class ClassName {
   public void method() {
      synchronized(ClassName.class) {
         // todo
      }
   }
}

使用總結(jié)

  • 無(wú)論synchronized關(guān)鍵字加在方法上還是對(duì)象上,如果它作用的對(duì)象是非靜態(tài)的,則它取得的鎖是對(duì)象;如果synchronized作用的對(duì)象是一個(gè)靜態(tài)方法或一個(gè)類(lèi),則它取得的鎖是對(duì)類(lèi),該類(lèi)所有的對(duì)象同一把鎖。
  • 每個(gè)對(duì)象只有一個(gè)鎖(lock)與之相關(guān)聯(lián),誰(shuí)拿到這個(gè)鎖誰(shuí)就可以運(yùn)行它所控制的那段代碼。
  • 實(shí)現(xiàn)同步是要很大的系統(tǒng)開(kāi)銷(xiāo)作為代價(jià)的,甚至可能造成死鎖,所以盡量避免無(wú)謂的同步控制。

三、synchronized的底層實(shí)現(xiàn)

synchronized的底層實(shí)現(xiàn),就不得不談數(shù)據(jù)在JVM內(nèi)存的存儲(chǔ):Java對(duì)象頭,以及Monitor對(duì)象監(jiān)視器。

對(duì)象頭

在JVM中,對(duì)象在內(nèi)存中的布局分為三塊區(qū)域:對(duì)象頭、實(shí)例數(shù)據(jù)和對(duì)齊填充。如下圖所示:

ac66e8ed41058ffcb9f66c011e2f2e5c.png

  • 實(shí)例數(shù)據(jù): 存放類(lèi)的屬性數(shù)據(jù)信息,包括父類(lèi)的屬性信息;
  • 對(duì)齊填充: 由于虛擬機(jī)要求 對(duì)象起始地址必須是8字節(jié)的整數(shù)倍。填充數(shù)據(jù)不是必須存在的,僅僅是為了字節(jié)對(duì)齊;
  • 對(duì)象頭: Java對(duì)象頭一般占有2個(gè)機(jī)器碼(在32位虛擬機(jī)中,1個(gè)機(jī)器碼等于4字節(jié),也就是32bit,在64位虛擬機(jī)中,1個(gè)機(jī)器碼是8個(gè)字節(jié),也就是64bit),但是如果對(duì)象是數(shù)組類(lèi)型,則需要3個(gè)機(jī)器碼,因?yàn)镴VM虛擬機(jī)可以通過(guò)Java對(duì)象的元數(shù)據(jù)信息確定Java對(duì)象的大小,但是無(wú)法從數(shù)組的元數(shù)據(jù)來(lái)確認(rèn)數(shù)組的大小,所以用一塊來(lái)記錄數(shù)組長(zhǎng)度。

synchronized用的鎖就是存在Java對(duì)象頭里的,那么什么是Java對(duì)象頭呢?Hotspot虛擬機(jī)的對(duì)象頭主要包括兩部分?jǐn)?shù)據(jù):Mark Word(標(biāo)記字段)、Class Pointer(類(lèi)型指針)。

其中 Class Pointer是對(duì)象指向它的類(lèi)元數(shù)據(jù)的指針,虛擬機(jī)通過(guò)這個(gè)指針來(lái)確定這個(gè)對(duì)象是哪個(gè)類(lèi)的實(shí)例,Mark Word用于存儲(chǔ)對(duì)象自身的運(yùn)行時(shí)數(shù)據(jù),它是實(shí)現(xiàn)輕量級(jí)鎖和偏向鎖的關(guān)鍵。

監(jiān)視器(Monitor)

任何一個(gè)對(duì)象都有一個(gè)Monitor與之關(guān)聯(lián),當(dāng)且一個(gè)Monitor被持有后,它將處于鎖定狀態(tài)。

synchronized在JVM里的實(shí)現(xiàn)都是 基于進(jìn)入和退出Monitor對(duì)象來(lái)實(shí)現(xiàn)方法同步和代碼塊同步,雖然具體實(shí)現(xiàn)細(xì)節(jié)不一樣,但是都可以通過(guò)成對(duì)的MonitorEnterMonitorExit指令來(lái)實(shí)現(xiàn)。

  • MonitorEnter指令: 插入在同步代碼塊的開(kāi)始位置,當(dāng)代碼執(zhí)行到該指令時(shí),將會(huì)嘗試獲取該對(duì)象Monitor的所有權(quán),即嘗試獲得該對(duì)象的鎖;
  • MonitorExit指令: 插入在方法結(jié)束處和異常處,JVM保證每個(gè)MonitorEnter必須有對(duì)應(yīng)的MonitorExit;

那什么是Monitor?可以把它理解為 一個(gè)同步工具,也可以描述為 一種同步機(jī)制,它通常被描述為一個(gè)對(duì)象。

與一切皆對(duì)象一樣,所有的Java對(duì)象是天生的Monitor,每一個(gè)Java對(duì)象都有成為Monitor的潛質(zhì),因?yàn)樵贘ava的設(shè)計(jì)中 ,每一個(gè)Java對(duì)象自打娘胎里出來(lái)就帶了一把看不見(jiàn)的鎖,它叫做內(nèi)部鎖或者M(jìn)onitor鎖。

也就是通常說(shuō)Synchronized的對(duì)象鎖,MarkWord鎖標(biāo)識(shí)位為10,其中指針指向的是Monitor對(duì)象的起始地址。在Java虛擬機(jī)(HotSpot)中,Monitor是由ObjectMonitor實(shí)現(xiàn)的。

四、synchronized 鎖的升級(jí)順序

鎖解決了數(shù)據(jù)的安全性,但是同樣帶來(lái)了性能的下降。hotspot 虛擬機(jī)的作者經(jīng)過(guò)調(diào)查發(fā)現(xiàn),大部分情況下,加鎖的代碼不僅僅不存在多線程競(jìng)爭(zhēng),而且總是由同一個(gè)線程多次獲得。所以基于這樣一個(gè)概率。

synchronized 在JDK1.6 之后做了一些優(yōu)化,為了減少獲得鎖和釋放鎖來(lái)的性能開(kāi)銷(xiāo),引入了偏向鎖、輕量級(jí)鎖、自旋鎖、重量級(jí)鎖,鎖的狀態(tài)根據(jù)競(jìng)爭(zhēng)激烈的程度從低到高不斷升級(jí)。

鎖主要存在四種狀態(tài),依次是:無(wú)鎖狀態(tài)、偏向鎖狀態(tài)、輕量級(jí)鎖狀態(tài)、重量級(jí)鎖狀態(tài),鎖可以從偏向鎖升級(jí)到輕量級(jí)鎖,再升級(jí)的重量級(jí)鎖。但是鎖的升級(jí)是單向的,也就是說(shuō)只能從低到高升級(jí),不會(huì)出現(xiàn)鎖的降級(jí)。而且這個(gè)過(guò)程就是開(kāi)銷(xiāo)逐漸加大的過(guò)程。

bd330342c2dac1f0674970e62bda2c82.png

到此這篇關(guān)于淺談Java的Synchronized鎖原理和優(yōu)化 的文章就介紹到這了,更多相關(guān)Synchronized鎖原理和優(yōu)化 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot整合mybatis-generator-maven-plugin的方法

    SpringBoot整合mybatis-generator-maven-plugin的方法

    這篇文章主要介紹了SpringBoot整合mybatis-generator-maven-plugin,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-11-11
  • springboot接入deepseek深度求索代碼示例(java版)

    springboot接入deepseek深度求索代碼示例(java版)

    這篇文章主要介紹了springboot接入deepseek深度求索的相關(guān)資料,包括創(chuàng)建APIKey,封裝詢問(wèn)工具方法,傳入問(wèn)題,調(diào)用方法,但發(fā)現(xiàn)只能回答簡(jiǎn)單問(wèn)題,需要的朋友可以參考下
    2025-01-01
  • java 中maven pom.xml文件教程詳解

    java 中maven pom.xml文件教程詳解

    這篇文章主要介紹了java 中maven pom.xml文件教程詳解,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2019-08-08
  • Java精品項(xiàng)目瑞吉外賣(mài)之登陸的完善與退出功能篇

    Java精品項(xiàng)目瑞吉外賣(mài)之登陸的完善與退出功能篇

    這篇文章主要為大家詳細(xì)介紹了java精品項(xiàng)目-瑞吉外賣(mài)訂餐系統(tǒng),此項(xiàng)目過(guò)大,分為多章獨(dú)立講解,本篇內(nèi)容為新增菜品和分頁(yè)查詢功能的實(shí)現(xiàn),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • java性能調(diào)優(yōu)System的gc垃圾回收方法

    java性能調(diào)優(yōu)System的gc垃圾回收方法

    這篇文章主要為大家介紹了java性能調(diào)優(yōu)System的gc垃圾回收方法示例解析有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步
    2022-03-03
  • AOP之事務(wù)管理<aop:advisor>的兩種配置方式

    AOP之事務(wù)管理<aop:advisor>的兩種配置方式

    這篇文章主要介紹了AOP之事務(wù)管理<aop:advisor>的兩種配置方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • java控制臺(tái)輸出圖書(shū)館管理系統(tǒng)

    java控制臺(tái)輸出圖書(shū)館管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了java控制臺(tái)輸出圖書(shū)館管理系統(tǒng),只用java代碼不用數(shù)據(jù)庫(kù)和GUI等,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-10-10
  • java定時(shí)任務(wù)實(shí)現(xiàn)的4種方式小結(jié)

    java定時(shí)任務(wù)實(shí)現(xiàn)的4種方式小結(jié)

    這篇文章主要介紹了java定時(shí)任務(wù)實(shí)現(xiàn)的4種方式小結(jié),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-09-09
  • Kotlin this詳解及實(shí)例

    Kotlin this詳解及實(shí)例

    這篇文章主要介紹了Kotlin this詳解及實(shí)例的相關(guān)資料,需要的朋友可以參考下
    2017-06-06
  • Java中的有限狀態(tài)機(jī)(設(shè)計(jì)模式——狀態(tài)模式)

    Java中的有限狀態(tài)機(jī)(設(shè)計(jì)模式——狀態(tài)模式)

    這篇文章主要介紹了Java中的有限狀態(tài)機(jī)(設(shè)計(jì)模式——狀態(tài)模式),具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-08-08

最新評(píng)論

龙川县| 象州县| 卢氏县| 桐梓县| 酒泉市| 克什克腾旗| 当涂县| 旌德县| 萝北县| 礼泉县| 德兴市| 辉县市| 莫力| 邵阳县| 库伦旗| 苏尼特右旗| 扎赉特旗| 隆子县| 湖州市| 会东县| 东台市| 武穴市| 家居| 遂溪县| 慈溪市| 施秉县| 大化| 抚顺县| 吉水县| 信宜市| 湄潭县| 双柏县| 北票市| 当涂县| 徐州市| 鱼台县| 罗甸县| 巴中市| 屯昌县| 四会市| 内黄县|