1. 程式人生 > >多執行緒 happens-before規則

多執行緒 happens-before規則

簡介 

   Java使用新的JSR-133記憶體模型,JSR-133使用happens-before的概念來闡述操作之間的記憶體可見性。在JMM中,如果一個操作執行的結果需要對另一個操作可見,那麼這兩個操作之間必須要存在happens-before關係。這裡提到的兩個操作既可以是在一個執行緒之內,也可以是在不同執行緒之間

規則

  1、程式順序規則:在一個單獨的執行緒中,按照程式程式碼的執行流順序,(時間上)先執行的操作happen—before(時間上)後執行的操作。

    2、管理鎖定規則:一個unlock操作happen—before後面(時間上的先後順序,下同)對同一個鎖的lock操作。

    3、volatile變數規則:對一個volatile變數的寫操作happen—before後面對該變數的讀操作。

    4、執行緒啟動規則:Thread物件的start()方法happen—before此執行緒的每一個動作。

    5、執行緒終止規則:執行緒的所有操作都happen—before對此執行緒的終止檢測,可以通過Thread.join()方法結束、Thread.isAlive()的返回值等手段檢測到執行緒已經終止執行。

    6、執行緒中斷規則:對執行緒interrupt()方法的呼叫happen—before發生於被中斷執行緒的程式碼檢測到中斷時事件的發生。

    7、物件終結規則:一個物件的初始化完成(建構函式執行結束)happen—before它的finalize()方法的開始。

    8、傳遞性:如果操作A happen—before操作B,操作B happen—before操作C,那麼可以得出A happen—before操作C。

需要注意的是

兩個操作之間具有happens-before關係,並不意味著前一個操作必須要在後一個操作之前執行!happens-before僅僅要求前一個操作(執行的結果)對後一個操作可見,且前一個操作按順序排在第二個操作之前。

happens-before的定義

happens-before的概念最初由Leslie Lamport在其一篇影響深遠的論文(《Time,Clocks and the Ordering of Events in a Distributed System》)中提出。Leslie Lamport使用happens-before來定義分散式系統中事件之間的偏序關係(partial ordering)。Leslie Lamport在這篇論文中給出了一個分散式演算法,該演算法可以將該偏序關係擴充套件為某種全序關係。

JSR-133使用happens-before的概念來指定兩個操作之間的執行順序。由於這兩個操作可以在一個執行緒之內,也可以是在不同執行緒之間。因此,JMM可以通過happens-before關係向程式設計師提供跨執行緒的記憶體可見性保證(如果A執行緒的寫操作a與B執行緒的讀操作b之間存在happens-before關係,儘管a操作和b操作在不同的執行緒中執行,但JMM向程式設計師保證a操作將對b操作可見)。

《JSR-133:Java Memory Model and Thread Specification》對happens-before關係的定義如下。

1)如果一個操作happens-before另一個操作,那麼第一個操作的執行結果將對第二個操作可見,而且第一個操作的執行順序排在第二個操作之前。

2)兩個操作之間存在happens-before關係,並不意味著Java平臺的具體實現必須要按照happens-before關係指定的順序來執行。如果重排序之後的執行結果,與按happens-before關係來執行的結果一致,那麼這種重排序並不非法(也就是說,JMM允許這種重排序)。

上面的1)是JMM對程式設計師的承諾。從程式設計師的角度來說,可以這樣理解happens-before關係:如果A happens-before B,那麼Java記憶體模型將向程式設計師保證——A操作的結果將對B可見,且A的執行順序排在B之前。注意,這只是Java記憶體模型向程式設計師做出的保證!

上面的2)是JMM對編譯器和處理器重排序的約束原則。正如前面所言,JMM其實是在遵循一個基本原則:只要不改變程式的執行結果(指的是單執行緒程式和正確同步的多執行緒程式),編譯器和處理器怎麼優化都行。JMM這麼做的原因是:程式設計師對於這兩個操作是否真的被重排序並不關心,程式設計師關心的是程式執行時的語義不能被改變(即執行結果不能被改變)。因此,happens-before關係本質上和as-if-serial語義是一回事。





相關推薦

執行 happens-before規則

簡介     Java使用新的JSR-133記憶體模型,JSR-133使用happens-before的概念來闡述操作之間的記憶體可見性。在JMM中,如果一個操作執行的結果需要對另一個操作可見,那麼這兩個操作之間必須要存在happens-before關係。這裡提到的兩個操

Java執行系列-happens-before規則和as-if-serial語義

JSR-133使用happens-before的概念來闡述操作之間的記憶體可見性。在JMM中,如果一個操作執行的結果需要對另一個操作可見, 那麼這2個操作之間必須要存在happens-before關係。這裡提到的2個操作既可以是一個執行緒之內,也可以是不同執行緒之間。

執行happens-before原則

下面就來具體介紹下happens-before原則(先行發生原則): ·        程式次序規則:一個執行緒內,按照程式碼順序,書寫在前面的操作先行發生於書寫在後面的操作 ·  &nb

從Java執行可見性談Happens-Before原則

這篇是轉載的,之前直接把連結嵌在文章裡,覺得還是獨立出來比較好。以下是正文: Happens-Before是一個非常抽象的概念,

執行的指令重排問題:as-if-serial語義,happens-before語義;volatile關鍵字,volatile和synchronized的區別

# 一、指令重排問題 你寫的程式碼有可能,根本沒有按照你期望的順序執行,因為**編譯器和 CPU 會嘗試指令重排來讓程式碼執行更高效**,這就是指令重排。 ## 1.1 虛擬機器層面 我們都知道CPU執行指令的時候,**訪問記憶體的速度遠慢於 CPU 速度**。 為了儘可能減少記憶體操作帶來的

Java執行-執行池ThreadPoolExecutor構造方法和規則 Java執行-執行池ThreadPoolExecutor構造方法和規則

Java多執行緒-執行緒池ThreadPoolExecutor構造方法和規則 2017年05月03日 17:15:37 閱讀數:40542 為什麼用執行緒池 部落格地址 http://blog.csdn.ne

Java執行-執行池ThreadPoolExecutor構造方法和規則

為什麼用執行緒池 有時候,系統需要處理非常多的執行時間很短的請求,如果每一個請求都開啟一個新執行緒的話,系統就要不斷的進行執行緒的建立和銷燬,有時花在建立和銷燬執行緒上的時間會比執行緒真正執行的時間還長。而且當執行緒數量太多時,系統不一定能受得了。 使用執

Java執行之happen-before簡介

在JDK5 開始,Java使用新的JSR-133記憶體模型,該模型使用happens-before的概念來闡述操作之間的記憶體可見性。在JMM中,如果一個操作執行的結果需要對另一個操作可見,那麼這兩個操作之間必須要存在happens-before關係。這裡提到的兩個操作既可以是一個執行緒之內,也可以

執行程式設計的8個規則

最近在學習網際網路方面相關的內容,找到一篇關於多執行緒設計原則的,我覺得挺好的,跟大家一塊分享出來; 規則一:找到真正不相關的計算任務  如果你將要執行的運算任務相互之間不獨立的話,你是不可能將它們並行化的。我可以很容易的舉出一些真實世界中相互獨立的任務如何為了達成同一個目

《JAVA執行程式設計的藝術》-volatile重排序規則理解

1.volatile寫的記憶體語義如下: 當寫一個volatile變數時,JMM會把該執行緒對應的本地記憶體中的共享變數重新整理到主記憶體。 2.volatile讀的記憶體語義如下: 當讀一個volatile變數時,JMM會把該執行緒對應的本地記憶體置為無效。執行

Windbg除錯----執行控制除錯

在除錯程式的時候,可能經常會有這樣的需求,讓一個執行緒在特定的時候才讓其開始執行或者暫停執行。比如複雜的多執行緒導致死鎖的問題,又或者多執行緒中的Race Condition 導致程式執行異常等。 很多時候,我們可以藉助編寫除錯程式碼來達到多執行緒的除錯,可是有些情況下除錯的執行粒度是指

Java執行實現電影院售票案例

某電影院目前正在上映賀歲大片,共有100張票,而它有3個售票視窗,請設計一個程式模擬該電影院售票。 定義Sell類實現Runnable介面,很好的解決了單繼承共享資源問題 public class Sell implements Runnable { // 定義100張票,三個售票

Objective-C高階程式設計:iOS與OS X執行和記憶體管理

這篇文章主要給大家講解一下GCD的平時不太常用的API,以及文末會貼出GCD定時器的一個小例子。 需要學習的朋友可以通過網盤免費下載pdf版 (先點選普通下載-----再選擇普通使用者就能免費下載了)http://putpan.com/fs/cy1i1beebn7s0h4u9/ 1.G

java執行物件鎖、類鎖、同步機制詳解

1.在java多執行緒程式設計中物件鎖、類鎖、同步機制synchronized詳解:     物件鎖:在java中每個物件都有一個唯一的鎖,物件鎖用於物件例項方法或者一個物件例項上面的。     類鎖:是用於一個類靜態方法或者class物件的,一個

面試題 執行 順序操作

問題 編寫一個程式,程式會啟動4個執行緒,向4個檔案A,B,C,D裡寫入資料,每個執行緒只能寫一個值。 執行緒A:只寫1 執行緒B:只寫2 執行緒C:只寫3 執行緒D:只寫4 4個檔案A,B,C,D。 程式執行起來,4個檔案的寫入結果如下:

Python執行程序和協程的例項講解

執行緒、程序和協程是什麼 執行緒、程序和協程的詳細概念解釋和原理剖析不是本文的重點,本文重點講述在Python中怎樣實際使用這三種東西 參考: 程序、執行緒、協程之概念理解 程序(Process)是計算機中的程式關於某資料集合上的一次執行活動,是系統進行資源分配和排程的基本單位,是作業系統結構的基礎。執

Java 執行實現死鎖場景

簡述: 《Java 程式設計思想》  P718 ~ P722 模擬死鎖的場景, 三個人 三根筷子,每個人需要拿到身邊的兩根筷子才能開始吃飯 出現死鎖的場景是,三個人都拿到了右邊的筷子,但是由於筷子都被搶佔,均無法獲得左邊的筷子 Chopstick.java

Java 執行 join和interrupt 方法

簡述: 使用Java多執行緒中join和interrupt函式 《Java程式設計思想》 P669 ~ P670 一個執行緒可以再其他執行緒上呼叫join()方法,其效果是等待一段時間直到第二個執行緒結束才繼續執行。 如果某個執行緒在另一個執行緒t上呼叫t.join(), 此

Java 執行 CountDownLatch 試用

簡述: 使用Java多執行緒的庫,包括 ExecutorService執行緒池, CountDownLatch執行緒執行控制(知道所有啟動的執行緒呼叫完成後,函式才會繼續執行) package test.anialy.multithread; import java.ut

執行筆試面試概念問答

點選此處檢視原文 第一題:執行緒的基本概念、執行緒的基本狀態及狀態之間的關係? 執行緒,有時稱為輕量級程序,是程式執行流的最小單元。一個標準的執行緒由執行緒ID,當前指令指標(PC),暫存器集合和堆疊組成。另外,執行緒是程序中的一個實體,是被系統獨立排程和分派的基本單位。它與屬於同一程序的其