中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java中怎么實現多線程的可見性與有序性

發布時間:2021-07-01 15:07:23 來源:億速云 閱讀:188 作者:Leah 欄目:大數據

本篇文章給大家分享的是有關Java中怎么實現多線程的可見性與有序性,小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。

多線程的可見性

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

共享變量

如果一個變量在多個線程的工作內存中都存在副本,那么這個變量就是這幾個線程的共享變量。

Java內存模型

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

  1. 所有的變量都存儲在主內存中

  2. 每個線程都有自己獨立的工作內存,里面保存該線程使用到的變量的副本(主內存中該變量的一份拷貝)

  3. 線程對共享變量的所有操作都必須在自己的工作內存中進行,不能直接從主內存中讀寫

  4. 不同線程之間無法直接訪問其他線程工作內存中的變量,線程間變量的傳遞需要通過主內存來完成

共享變量可見性實現的原理

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

  1. 把工作內存1中更新過的共享變量刷新到主內存中

  2. 將主內存中最新的共享變量的值更新到工作內存2中

Java的內存模型: Java中怎么實現多線程的可見性與有序性

Java語言層面支持的可見性實現方式有以下兩種:

  1. synchronized

  2. volatile

synchronized

JMM關于synchronized的規定:

  • 線程解鎖前,必須把共享變量的最新值刷新到主內存中

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

因此線程執行synchronized代碼執行互斥鎖的過程:

  1. 獲得互斥鎖。

  2. 清空工作內存。

  3. 從主內存拷貝變量的最新副本到工作內存。

  4. 執行代碼

  5. 將更改后的共享變量的值刷新到主內存中

  6. 釋放互斥鎖

synchronize在JDK6之后,進行了很多優化。更多synchroinzed的講解,點擊查看:詳解Java多線程鎖之synchronized

volatile

不能保證原子性,但適合使用volatile修飾狀態標記量

通過加入內存屏障和禁止重排序優化來實現的

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

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

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

volatile寫操作: Java中怎么實現多線程的可見性與有序性

volatile讀操作: Java中怎么實現多線程的可見性與有序性

多線程的有序性

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

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

  1. 編譯器優化的重排序(編譯器優化)

  2. 指令集并行重排序(處理器優化)

  3. 內存系統的重排序(處理器優化)

happens-before原則

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

  • 程序次序規則:在一個線程內一段代碼的執行結果是有序的。就是還會指令重排,但是隨便它怎么排,結果是按照我們代碼的順序生成的不會變!

  • 管程鎖定規則:就是無論是在單線程環境還是多線程環境,對于同一個鎖來說,一個線程對這個鎖解鎖之后,另一個線程獲取了這個鎖都能看到前一個線程的操作結果!(管程是一種通用的同步原語,synchronized就是管程的實現)

  • volatile變量規則:就是如果一個線程先去寫一個volatile變量,然后一個線程去讀這個變量,那么這個寫操作的結果一定對讀的這個線程可見。

  • 傳遞規則:happens-before原則具有傳遞性,即A happens-before B , B happens-before C,那么A happens-before C。

  • 線程啟動規則:在主線程A執行過程中,啟動子線程B,那么線程A在啟動子線程B之前對共享變量的修改結果對線程B可見。

  • 線程終止規則:在主線程A執行過程中,子線程B終止,那么線程B在終止之前對共享變量的修改結果在線程A中可見。

  • 線程中斷規則:對線程interrupt()方法的調用先行發生于被中斷線程代碼檢測到中斷事件的發生,可以通過Thread.interrupted()檢測到是否發生中斷。

  • 對象終結規則:一個對象的初始化的完成,也就是構造函數執行的結束一定 happens-before它的finalize()方法。

以上就是Java中怎么實現多線程的可見性與有序性,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

安多县| 平湖市| 奉节县| 五河县| 勃利县| 滦平县| 陕西省| 东安县| 静海县| 清水县| 崇义县| 留坝县| 九江县| 忻城县| 偏关县| 凤凰县| 桃园市| 于都县| 岳阳市| 屏山县| 修文县| 卓尼县| 昌平区| 双峰县| 体育| 望谟县| 察哈| 翁牛特旗| 威信县| 金川县| 酒泉市| 新疆| 塔河县| 抚顺县| 海城市| 镇沅| 高要市| 郓城县| 莫力| 清远市| 和顺县|