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

Java中鎖的實(shí)現(xiàn)和內(nèi)存語(yǔ)義淺析

 更新時(shí)間:2018年11月15日 15:03:01   作者:蝸牛大師  
這篇文章主要給大家介紹了關(guān)于Java中鎖的實(shí)現(xiàn)和內(nèi)存語(yǔ)義的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

1. 概述

鎖是Java并發(fā)編程中最重要的同步機(jī)制。鎖除了讓臨界區(qū)互斥執(zhí)行外,還可以讓釋放鎖的線程獲取同一個(gè)鎖的線程發(fā)送消息。

鎖在實(shí)際使用時(shí)只是明白鎖限制了并發(fā)訪問(wèn), 但是鎖是如何實(shí)現(xiàn)并發(fā)訪問(wèn)的, 同學(xué)們可能不太清楚, 下面這篇文章就來(lái)揭開(kāi)鎖的神秘面紗.

2. 鎖的內(nèi)存語(yǔ)義

  • 當(dāng)線程獲取鎖時(shí), JMM會(huì)把線程對(duì)應(yīng)的本地內(nèi)存置為無(wú)效. 從而使得被監(jiān)視器保護(hù)的臨界區(qū)的變量必須從主內(nèi)存中讀取.
  • 當(dāng)線程釋放鎖時(shí), JMM會(huì)把該線程對(duì)應(yīng)的本地內(nèi)存中的共享變量刷新到主內(nèi)存中(并不是不釋放鎖就不刷新到主內(nèi)存, 只是釋放鎖時(shí)把未刷新到主內(nèi)存中的數(shù)據(jù)刷新到主內(nèi)存).

鎖的內(nèi)存語(yǔ)義與volatile的內(nèi)存語(yǔ)義

  • 鎖獲取與volatile讀有相同的內(nèi)存語(yǔ)義.
  • 鎖釋放與volatile寫(xiě)有相同的內(nèi)存語(yǔ)義.

內(nèi)存語(yǔ)義總結(jié)

  • 線程A釋放一個(gè)鎖, 實(shí)質(zhì)上是線程A向接下來(lái)將要獲取這個(gè)鎖的某個(gè)線程發(fā)出了(線程A對(duì)共享變量所做修改的)消息.
  • 線程B獲取一個(gè)鎖, 實(shí)質(zhì)上是線程B接收了之前某個(gè)線程發(fā)出的(在釋放這個(gè)鎖之前對(duì)共享變量所做修改的)消息.
  • 線程A釋放鎖, 隨后線程B獲取這個(gè)鎖, 這個(gè)過(guò)程實(shí)質(zhì)上是線程A通過(guò)主內(nèi)存向線程B發(fā)送消息.

3. 鎖內(nèi)存語(yǔ)義的實(shí)現(xiàn)

下面以ReentrantLock為例, 獲取到鎖就是把state改為1(不考慮重入), 釋放鎖時(shí)改為0.

而加鎖的關(guān)鍵代碼就是

protected final boolean compareAndSetState(int expect, int update) {
 return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}

該方法以原子操作的方式更新state變量, 本文把Java的compareAndSet()方法簡(jiǎn)稱(chēng)為CAS. JDK文檔對(duì)該方法的說(shuō)明如下: 如果當(dāng)前狀態(tài)值等于預(yù)期值, 則以原子方式將同步狀態(tài)設(shè)置為給定的更新值. 此操作具有volatile讀和寫(xiě)的內(nèi)存語(yǔ)義.

這里我們分別從編譯器和處理器的角度來(lái)分析: CAS如何同時(shí)具有volatile讀和volatile寫(xiě)的內(nèi)存語(yǔ)義.

我們知道, 編譯器不會(huì)對(duì)volatile讀與volatile讀后面的任意內(nèi)存操作重排序; 編譯器不會(huì)對(duì)volatile寫(xiě)與volatile寫(xiě)前面的任意內(nèi)存操作重排序. 組合這兩個(gè)條件, 意味著為了同時(shí)實(shí)現(xiàn)volatile讀和volatile寫(xiě)的內(nèi)存語(yǔ)義, 編譯器不能對(duì)CAS與CAS前面和后面的任意內(nèi)存操作重排序.

下面我們來(lái)分析在常見(jiàn)的intel X86處理器中, CAS是如何同時(shí)具有volatile讀和volatile寫(xiě)的內(nèi)存語(yǔ)義的.

下面是sun.misc.Unsafe類(lèi)的compareAndSwapInt()方法的源代碼.

public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);

可以看到, 這是一個(gè)本地方法調(diào)用. 這個(gè)本地方法在openjdk中依次調(diào)用的c++代碼為: unsafe.cpp, atomic.cpp 和 atomic_windows_x86.inline.hpp. 這個(gè)本地方法的最終實(shí)現(xiàn)在openjdk的如下位置: openjdk-7-fcs-src-b147-
27_jun_2011\openjdk\hotspot\src\os_cpu\windows_x86\vm\atomic_windows_x86.inline.hpp(對(duì)應(yīng)于
Windows操作系統(tǒng), X86處理器). 下面是對(duì)應(yīng)于intel X86處理器的源代碼的片段.

inline jint Atomic::cmpxchg (jint exchange_value, volatile jint* dest, jint compare_value) {
 // alternative for InterlockedCompareExchange
 int mp = os::is_MP();
 __asm {
  mov edx, dest
  mov ecx, exchange_value
  mov eax, compare_value
  LOCK_IF_MP(mp)
  cmpxchg dword ptr [edx], ecx
 }
}

如上面源代碼所示, 程序會(huì)根據(jù)當(dāng)前處理器的類(lèi)型來(lái)決定是否為cmpxchg指令添加lock前綴. 如果程序是在多處理器上運(yùn)行, 就為cmpxchg指令加上lock前綴(Lock Cmpxchg). 反之, 如果程序是在單處理器上運(yùn)行, 就省略lock前綴(單處理器自身會(huì)維護(hù)單處理器內(nèi)的順序一致性, 不需要lock前綴提供的內(nèi)存屏障效果).

intel的手冊(cè)對(duì)lock前綴的說(shuō)明如下.

  • 確保對(duì)內(nèi)存的讀-改-寫(xiě)操作原子執(zhí)行. 在Pentium及Pentium之前的處理器中, 帶有l(wèi)ock前綴的指令在執(zhí)行期間會(huì)鎖住總線, 使得其他處理器暫時(shí)無(wú)法通過(guò)總線訪問(wèn)內(nèi)存. 很顯然, 這會(huì)帶來(lái)昂貴的開(kāi)銷(xiāo). 從Pentium 4、Intel Xeon及P6處理器開(kāi)始, Intel使用緩存鎖定(Cache Locking)
    來(lái)保證指令執(zhí)行的原子性. 緩存鎖定將大大降低lock前綴指令的執(zhí)行開(kāi)銷(xiāo).
  • 禁止該指令, 與之前和之后的讀和寫(xiě)指令重排序.
  • 把寫(xiě)緩沖區(qū)中的所有數(shù)據(jù)刷新到內(nèi)存中.

上面的第2點(diǎn)和第3點(diǎn)所具有的內(nèi)存屏障效果, 足以同時(shí)實(shí)現(xiàn)volatile讀和volatile寫(xiě)的內(nèi)存語(yǔ)義.

經(jīng)過(guò)上面的分析, 現(xiàn)在我們終于能明白為什么JDK文檔說(shuō)CAS同時(shí)具有volatile讀和volatile寫(xiě)的內(nèi)存語(yǔ)義了.

從本文對(duì)ReentrantLock的分析可以看出, 鎖釋放-獲取的內(nèi)存語(yǔ)義的實(shí)現(xiàn)至少有下面兩種方式.

  • 利用volatile變量的寫(xiě)-讀所具有的內(nèi)存語(yǔ)義.
  • 利用CAS所附帶的volatile讀和volatile寫(xiě)的內(nèi)存語(yǔ)義.

4. 總結(jié)

對(duì)于鎖, 可以這么理解, N個(gè)線程去通過(guò)CAS去修改一個(gè)volatile變量, 但是由于CPU提供的機(jī)制, 只能有一個(gè)線程修改成功, 修改成功的線程獲得鎖, 其它線程以及后來(lái)的線程要么自旋一會(huì)兒, 要么直接掛起, 等待獲取鎖的線程釋放鎖時(shí)去喚醒. 就是這么個(gè)過(guò)程.

好了,以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。

相關(guān)文章

  • Spring自定義注解實(shí)現(xiàn)接口版本管理

    Spring自定義注解實(shí)現(xiàn)接口版本管理

    這篇文章主要介紹了Spring自定義注解實(shí)現(xiàn)接口版本管理,RequestMappingHandlerMapping類(lèi)是與 @RequestMapping相關(guān)的,它定義映射的規(guī)則,即滿(mǎn)足怎樣的條件則映射到那個(gè)接口上,需要的朋友可以參考下
    2023-11-11
  • MyBatis實(shí)現(xiàn)表連接查詢(xún)寫(xiě)法(三種對(duì)應(yīng)關(guān)系)的方法總結(jié)

    MyBatis實(shí)現(xiàn)表連接查詢(xún)寫(xiě)法(三種對(duì)應(yīng)關(guān)系)的方法總結(jié)

    這篇文章主要介紹了MyBatis實(shí)現(xiàn)表連接查詢(xún)寫(xiě)法(一對(duì)一關(guān)系、一對(duì)多關(guān)系、多對(duì)多關(guān)系)的方法,文中的示例代碼講解詳細(xì),感興趣的可以了解一下
    2023-01-01
  • java用split分割字符串的一個(gè)有趣現(xiàn)象

    java用split分割字符串的一個(gè)有趣現(xiàn)象

    最近在項(xiàng)目中使用了java中的split分割字符串,發(fā)現(xiàn)了一個(gè)bug,充分了展示了自己對(duì)java底層的認(rèn)知有很多的不足和欠缺。下面將這次的經(jīng)過(guò)總結(jié)出來(lái)分享給大家,有需要的朋友們可以參考借鑒,下面來(lái)一起看看吧。
    2016-12-12
  • JEE與Spring Boot代碼性能比較分析

    JEE與Spring Boot代碼性能比較分析

    JavaEE與Spring Boot其實(shí)很難比較測(cè)試,前者適合單體SOA架構(gòu),后者適合微服務(wù),但是還是有好事者把兩者放在一起比較性能。這篇文章主要介紹了JEE與Spring Boot代碼性能比較,需要的朋友可以參考下
    2018-11-11
  • Java工程中可執(zhí)行JAR兩種打包方式詳解

    Java工程中可執(zhí)行JAR兩種打包方式詳解

    這篇文章主要為大家詳細(xì)介紹了Java工程中可執(zhí)行JAR兩種打包方式,一體化可執(zhí)行包和帶外部依賴(lài)lib的可執(zhí)行包,有需要的小伙伴可以學(xué)習(xí)一下
    2024-04-04
  • Java中的密碼加密方式

    Java中的密碼加密方式

    文章介紹了Java中使用MD5算法對(duì)密碼進(jìn)行加密的方法,以及如何通過(guò)加鹽和多重加密來(lái)提高密碼的安全性,MD5是一種不可逆的哈希算法,適合用于存儲(chǔ)密碼,因?yàn)槠漭敵龅恼L(zhǎng)度固定,且不容易發(fā)生碰撞,此外,通過(guò)加鹽和多重加密,可以進(jìn)一步增加密碼的復(fù)雜性和安全性
    2025-01-01
  • Java 如何使用@Autowired注解自動(dòng)注入bean

    Java 如何使用@Autowired注解自動(dòng)注入bean

    這篇文章主要介紹了Java 使用@Autowired注解自動(dòng)注入bean的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • SpringBoot AOP處理請(qǐng)求日志打印功能代碼實(shí)例

    SpringBoot AOP處理請(qǐng)求日志打印功能代碼實(shí)例

    這篇文章主要介紹了SpringBoot AOP處理請(qǐng)求日志打印功能代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-03-03
  • springboot themaleaf 第一次進(jìn)頁(yè)面不加載css的問(wèn)題

    springboot themaleaf 第一次進(jìn)頁(yè)面不加載css的問(wèn)題

    這篇文章主要介紹了springboot themaleaf 第一次進(jìn)頁(yè)面不加載css的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-10-10
  • MyBatis 與 Spring 的完美整合方法

    MyBatis 與 Spring 的完美整合方法

    MyBatis 和 Spring 兩大框架已經(jīng)成了 Java 互聯(lián)網(wǎng)技術(shù)主流框架組合,它們經(jīng)受住了大數(shù)據(jù)量和大批量請(qǐng)求的考驗(yàn),在互聯(lián)網(wǎng)系統(tǒng)中得到了廣泛的應(yīng)用。這篇文章主要介紹了MyBatis 與 Spring 整合,需要的朋友可以參考下
    2018-04-04

最新評(píng)論

辽中县| 东方市| 大冶市| 清水河县| 东山县| 永福县| 乌兰浩特市| 黄大仙区| 安泽县| 永安市| 兰西县| 玉田县| 镇巴县| 澄江县| 长葛市| 洛宁县| 开阳县| 丰城市| 大兴区| 泸州市| 宿迁市| 台南市| 仙游县| 玉田县| 淅川县| 深水埗区| 益阳市| 包头市| 威信县| 清河县| 常宁市| 白朗县| 元氏县| 克山县| 股票| 乐安县| 雅江县| 都江堰市| 墨竹工卡县| 阳曲县| 饶河县|