欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

了解Java多線程的可見(jiàn)性與有序性

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

多線程的可見(jiàn)性

一個(gè)線程對(duì)共享變量值的修改,能夠及時(shí)的被其他線程看到。

共享變量

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

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

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

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

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

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

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

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

  • synchronized
  • volatile

synchronized

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

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

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

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

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

volatile

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

  • 在每個(gè)volatile寫(xiě)操作前插入StoreStore屏障,在寫(xiě)操作后插入StoreLoad屏障
  • 在每個(gè)volatile讀操作前插入LoadLoad屏障,在讀操作后插入LoadStore屏障

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

volatile寫(xiě)操作:

volatile讀操作:

多線程的有序性

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

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

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

happens-before原則

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

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

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

相關(guān)文章

  • 謹(jǐn)慎使用Java8的默認(rèn)方法

    謹(jǐn)慎使用Java8的默認(rèn)方法

    為什么要謹(jǐn)慎使用Java8的默認(rèn)方法?本文給出了為什么要慎用Java8默認(rèn)方法的原因,解釋的很詳細(xì),感興趣的朋友可以參考一下
    2016-01-01
  • 關(guān)于@JsonProperty,@NotNull,@JsonIgnore的具體使用

    關(guān)于@JsonProperty,@NotNull,@JsonIgnore的具體使用

    這篇文章主要介紹了關(guān)于@JsonProperty,@NotNull,@JsonIgnore的具體使用,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-08-08
  • SpringBoot實(shí)現(xiàn)圖片防盜鏈功能

    SpringBoot實(shí)現(xiàn)圖片防盜鏈功能

    出于安全考慮,我們需要后端返回的圖片只允許在某個(gè)網(wǎng)站內(nèi)展示,不想被爬蟲(chóng)拿到圖片地址后被下載,或者,不想瀏覽器直接訪問(wèn)圖片鏈接,所以本文將給大家介紹SpringBoot實(shí)現(xiàn)圖片防盜鏈功能,需要的朋友可以參考下
    2024-04-04
  • 深度解析Java中ArrayList的使用

    深度解析Java中ArrayList的使用

    ArrayList?類是一個(gè)可以動(dòng)態(tài)修改的數(shù)組,與普通數(shù)組的區(qū)別就是它是沒(méi)有固定大小的限制,我們可以添加或刪除元素。本文將通過(guò)示例帶你深度解析Java中ArrayList的使用,需要的可以參考一下
    2022-09-09
  • java實(shí)現(xiàn)的漢字轉(zhuǎn)五筆功能實(shí)例

    java實(shí)現(xiàn)的漢字轉(zhuǎn)五筆功能實(shí)例

    這篇文章主要介紹了java實(shí)現(xiàn)的漢字轉(zhuǎn)五筆功能,結(jié)合具體實(shí)例形式分析了java基于字符串遍歷與編碼轉(zhuǎn)換等操作實(shí)現(xiàn)五筆編碼獲取的相關(guān)操作技巧,需要的朋友可以參考下
    2017-06-06
  • Springboot測(cè)試類沒(méi)有bean注入問(wèn)題解析

    Springboot測(cè)試類沒(méi)有bean注入問(wèn)題解析

    這篇文章主要介紹了Springboot測(cè)試類沒(méi)有bean注入問(wèn)題解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-12-12
  • Java語(yǔ)言中的文件數(shù)據(jù)流示例詳解

    Java語(yǔ)言中的文件數(shù)據(jù)流示例詳解

    這篇文章主要為大家介紹了Java語(yǔ)言中的文件數(shù)據(jù)流示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-11-11
  • MybatisPlus?構(gòu)造器wrapper的使用與原理解析

    MybatisPlus?構(gòu)造器wrapper的使用與原理解析

    本次我們介紹了MybatisPlus?構(gòu)造器wrapper的使用方式及其易錯(cuò)點(diǎn),同時(shí)也針對(duì)其運(yùn)行的原理進(jìn)行了解釋,只有深刻理解了它的原理,我們才能更靈活的使用,并且更快的排查出問(wèn)題,感興趣的朋友跟隨小編一起看看吧
    2024-05-05
  • Java中的隨機(jī)數(shù)詳解

    Java中的隨機(jī)數(shù)詳解

    這篇文章主要介紹了Java中的隨機(jī)數(shù),需要的朋友可以參考下
    2014-02-02
  • elasticsearch集群發(fā)現(xiàn)zendiscovery的Ping機(jī)制分析

    elasticsearch集群發(fā)現(xiàn)zendiscovery的Ping機(jī)制分析

    這篇文章主要為大家介紹了elasticsearch集群發(fā)現(xiàn)zendiscovery的Ping機(jī)制分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-04-04

最新評(píng)論