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

了解Java多線程的可見性與有序性

 更新時間:2019年06月19日 12:02:46   作者:mseddl  
這篇文章主要介紹了了解Java多線程的可見性與有序性,在Java內(nèi)存模型中,允許編譯器和處理器對指令進(jìn)行重排序,但是重排序過程不會影響到單線程程序的執(zhí)行,卻會影響到多線程并發(fā)執(zhí)行的正確性。,需要的朋友可以參考下

多線程的可見性

一個線程對共享變量值的修改,能夠及時的被其他線程看到。

共享變量

如果一個變量在多個線程的工作內(nèi)存中都存在副本,那么這個變量就是這幾個線程的共享變量。
Java內(nèi)存模型

JMM(Java Memory Model,簡稱JMM)描述了Java程序中各種變量(線程共享變量)的訪問規(guī)則,以及在JVM中將變量存儲到內(nèi)存和從內(nèi)存中讀取出變量這樣的底層細(xì)節(jié)。它遵循四個原則:

  1. 所有的變量都存儲在主內(nèi)存中
  2. 每個線程都有自己獨(dú)立的工作內(nèi)存,里面保存該線程使用到的變量的副本(主內(nèi)存中該變量的一份拷貝)
  3. 線程對共享變量的所有操作都必須在自己的工作內(nèi)存中進(jìn)行,不能直接從主內(nèi)存中讀寫
  4. 不同線程之間無法直接訪問其他線程工作內(nèi)存中的變量,線程間變量的傳遞需要通過主內(nèi)存來完成

共享變量可見性實(shí)現(xiàn)的原理

線程1對共享變量的修改要想被線程2及時看到,必須經(jīng)過如下2個步驟:

  1. 把工作內(nèi)存1中更新過的共享變量刷新到主內(nèi)存中
  2. 將主內(nèi)存中最新的共享變量的值更新到工作內(nèi)存2中

Java的內(nèi)存模型:

Java語言層面支持的可見性實(shí)現(xiàn)方式有以下兩種:

  • synchronized
  • volatile

synchronized

JMM關(guān)于synchronized的規(guī)定:

  • 線程解鎖前,必須把共享變量的最新值刷新到主內(nèi)存中
  • 線程加鎖時,將清空工作內(nèi)存中存儲的共享變量的值,從而使用共享變量時,必須從主內(nèi)存中重新讀取最新的值。(注意:解鎖和加鎖,是指同一把鎖)

因此線程執(zhí)行synchronized代碼執(zhí)行互斥鎖的過程:

  1. 獲得互斥鎖。
  2. 清空工作內(nèi)存。
  3. 從主內(nèi)存拷貝變量的最新副本到工作內(nèi)存。
  4. 執(zhí)行代碼
  5. 將更改后的共享變量的值刷新到主內(nèi)存中
  6. 釋放互斥鎖

synchronize在JDK6之后,不單單是互斥鎖。

volatile

不能保證原子性,但適合使用volatile修飾狀態(tài)標(biāo)記量
通過加入內(nèi)存屏障和禁止重排序優(yōu)化來實(shí)現(xiàn)的

  • 在每個volatile寫操作前插入StoreStore屏障,在寫操作后插入StoreLoad屏障
  • 在每個volatile讀操作前插入LoadLoad屏障,在讀操作后插入LoadStore屏障

通俗地講:volatile變量在每次被線程訪問時,都強(qiáng)迫從主內(nèi)存中重讀該變量的值,而當(dāng)該變量發(fā)生變化時,又會強(qiáng)迫將最新的值刷新到主內(nèi)存。這樣任何時刻,不同的線程總能看到該變量的最新值。

volatile寫操作:

volatile讀操作:

多線程的有序性

在Java內(nèi)存模型中,允許編譯器和處理器對指令進(jìn)行重排序,但是重排序過程不會影響到單線程程序的執(zhí)行,卻會影響到多線程并發(fā)執(zhí)行的正確性。

指令重排序:代碼書寫的順序與實(shí)際執(zhí)行的順序不同,指令重排序是編譯器或者處理器為了提高程序性能而做的優(yōu)化。

  • 編譯器優(yōu)化的重排序(編譯器優(yōu)化)
  • 指令集并行重排序(處理器優(yōu)化)
  • 內(nèi)存系統(tǒng)的重排序(處理器優(yōu)化)

happens-before原則

JMM可以通過happens-before關(guān)系向程序員提供跨線程的內(nèi)存可見性保證(如果A線程的寫操作a與B線程的讀操作b之間存在happens-before關(guān)系,盡管a操作和b操作在不同的線程中執(zhí)行,但JMM向程序員保證a操作將對b操作可見)。

  • 程序次序規(guī)則:在一個線程內(nèi)一段代碼的執(zhí)行結(jié)果是有序的。就是還會指令重排,但是隨便它怎么排,結(jié)果是按照我們代碼的順序生成的不會變!
  • 管程鎖定規(guī)則:就是無論是在單線程環(huán)境還是多線程環(huán)境,對于同一個鎖來說,一個線程對這個鎖解鎖之后,另一個線程獲取了這個鎖都能看到前一個線程的操作結(jié)果!(管程是一種通用的同步原語,synchronized就是管程的實(shí)現(xiàn))
  • volatile變量規(guī)則:就是如果一個線程先去寫一個volatile變量,然后一個線程去讀這個變量,那么這個寫操作的結(jié)果一定對讀的這個線程可見。
  • 傳遞規(guī)則:happens-before原則具有傳遞性,即A happens-before B , B happens-before C,那么A happens-before C。
  • 線程啟動規(guī)則:在主線程A執(zhí)行過程中,啟動子線程B,那么線程A在啟動子線程B之前對共享變量的修改結(jié)果對線程B可見。
  • 線程終止規(guī)則:在主線程A執(zhí)行過程中,子線程B終止,那么線程B在終止之前對共享變量的修改結(jié)果在線程A中可見。
  • 線程中斷規(guī)則:對線程interrupt()方法的調(diào)用先行發(fā)生于被中斷線程代碼檢測到中斷事件的發(fā)生,可以通過Thread.interrupted()檢測到是否發(fā)生中斷。
  • 對象終結(jié)規(guī)則:一個對象的初始化的完成,也就是構(gòu)造函數(shù)執(zhí)行的結(jié)束一定 happens-before它的finalize()方法。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

  • Spring Security基于自定義的認(rèn)證提供器實(shí)現(xiàn)圖形驗(yàn)證碼流程解析

    Spring Security基于自定義的認(rèn)證提供器實(shí)現(xiàn)圖形驗(yàn)證碼流程解析

    這篇文章主要介紹了Spring Security基于自定義的認(rèn)證提供器實(shí)現(xiàn)圖形驗(yàn)證碼,通過本文學(xué)習(xí)下AuthenticationProvider接口的類關(guān)系圖,感興趣的朋友跟隨小編一起看看吧
    2021-09-09
  • springboot jackson自定義序列化和反序列化實(shí)例

    springboot jackson自定義序列化和反序列化實(shí)例

    這篇文章主要介紹了spring boot jackson自定義序列化和反序列化實(shí)例,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • IDEA報錯:java?找不到符號圖文解決過程

    IDEA報錯:java?找不到符號圖文解決過程

    這篇文章主要給大家介紹了關(guān)于IDEA報錯:java?找不到符號解決的相關(guān)資料,運(yùn)行項目時Idea報錯,提示找不到符號,但是這個類在項目里是存在的,網(wǎng)上找了很多文章都沒解決,浪費(fèi)了一個下午終于弄好了,記錄一下,需要的朋友可以參考下
    2023-08-08
  • Java基于socket實(shí)現(xiàn)簡易聊天室實(shí)例

    Java基于socket實(shí)現(xiàn)簡易聊天室實(shí)例

    這篇文章主要介紹了Java基于socket實(shí)現(xiàn)簡易聊天室的方法,實(shí)例分析了java基于socket實(shí)現(xiàn)聊天室服務(wù)端與客戶端的相關(guān)技巧,需要的朋友可以參考下
    2015-05-05
  • 詳解SpringCloud mysql實(shí)現(xiàn)配置中心

    詳解SpringCloud mysql實(shí)現(xiàn)配置中心

    這篇文章主要介紹了詳解SpringCloud mysql實(shí)現(xiàn)配置中心,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-09-09
  • 詳解Java中的時區(qū)類TimeZone的用法

    詳解Java中的時區(qū)類TimeZone的用法

    TimeZone可以用來獲取或者規(guī)定時區(qū),也可以用來計算時差,這里我們就來詳解Java中的時區(qū)類TimeZone的用法,特別要注意下面所提到的TimeZone相關(guān)的時間校準(zhǔn)問題.
    2016-06-06
  • Java中Base64和File之間互轉(zhuǎn)代碼示例

    Java中Base64和File之間互轉(zhuǎn)代碼示例

    這篇文章主要給大家介紹了關(guān)于Java中Base64和File之間互轉(zhuǎn)的相關(guān)資料,Base64是網(wǎng)絡(luò)上最常見的用于傳輸8Bit字節(jié)碼的編碼方式之一,Base64就是一種基于64個可打印字符來表示二進(jìn)制數(shù)據(jù)的方法,需要的朋友可以參考下
    2023-08-08
  • 如何將maven項目導(dǎo)出jar包(最簡單方法)

    如何將maven項目導(dǎo)出jar包(最簡單方法)

    大家都知道對于將maven項目導(dǎo)出jar包有好幾種方式,本文給大家分享一種方式最容易且最方便,感興趣的朋友跟隨小編一起看看吧
    2023-11-11
  • Java使用StampedLock實(shí)現(xiàn)高效讀寫功能

    Java使用StampedLock實(shí)現(xiàn)高效讀寫功能

    StampedLock 是 Java 8 引入的高性能鎖,提供了三種鎖模式:寫鎖、悲觀讀鎖和樂觀讀鎖,與傳統(tǒng)的 ReentrantReadWriteLock 相比,StampedLock 更注重性能,特別適合讀多寫少的場景,所以本文給大家介紹了Java使用StampedLock實(shí)現(xiàn)高效讀寫功能,需要的朋友可以參考下
    2025-01-01
  • 最新評論

    白山市| 嘉禾县| 南漳县| 留坝县| 崇义县| 拉萨市| 榕江县| 磐安县| 防城港市| 广昌县| 阿鲁科尔沁旗| 泰宁县| 开平市| 措美县| 班戈县| 菏泽市| 连州市| 双桥区| 潮安县| 霍州市| 金阳县| 娄底市| 阿克陶县| 汕尾市| 来凤县| 温州市| 黑水县| 井冈山市| 兴安盟| 漳浦县| 昌宁县| 都昌县| 方山县| 普定县| 固阳县| 滨海县| 安徽省| 崇州市| 荆州市| 丽江市| 咸宁市|