当前位置:网站首页>Deep understanding of happens before principle

Deep understanding of happens before principle

2022-06-27 10:55:00 Chenshuyi

In the previous article , We have a deep understanding of Java Memory model , got it Java The significance of the memory model , And the problems to be solved . Finally we know :Java The memory model defines 8 Basic operations and 8 A rule , Just follow these rules for concurrent operations , Then they are safe .

Even those who are stronger than brother Shu , Look at this 16 This rule is also a headache . They are too cumbersome , It is very disadvantageous to our daily code writing . To help programmers understand , Therefore, there is the judgment principle of equal price —— Antecedent principle , It can be used to determine whether an access is safe in a concurrent environment .

Come here , We need to understand :happens-before The principle is to Java Simplification of memory model , Let's better write concurrent code . It's like Java Language and other high-level languages , For assembly language 、 Machine language and other low-level languages , It can protect programmers from 「 The pain of flesh and skin 」.

What is? happens-before?

happens-before refer to Java The sequential relationship between the two operations in the memory model . For example, operation A Prior to operation B, That is to say, operation A It happens in the operation B Before , operation A The impact can be manipulated B The observed . there 「 influence 」 Include : Values of shared variables in memory 、 Sent a message 、 Method called, etc .

Take a very simple example : In the following code i=1 In a thread A In the implementation of , and j=i In a thread B In the implementation of . because i=1 Operation precedes j=i perform , that i=1 The result of the operation should be able to be processed by the thread B The observed .

//  In a thread  A  In the implementation of 
i = 1;
//  In a thread  B  In the implementation of 
j = i;

Java There are... Under the memory model 8 strip happens-before The rules , If the operation between threads cannot be derived from the following rules , Then there is no sequential guarantee for their operation , Virtual machines or operating systems can be reordered at will , Thus, concurrent security problems may occur .

  • Program Order Rule (Program Order Rule): In a thread , In order of program code , The operation of writing before takes place before the operation of writing after . To be exact , It should be the order of the control flow, not the sequence of the program code , Because we need to think about branches 、 Circulation and other structures .
  • Tube lock rule (Monitor Lock Rule): One unlock The operation occurs first of all on the same lock lock operation . The same lock must be emphasized here , and “ Back ” The order of time .
  • volatile Variable rule (Volatile Variable Rule): To a volatile The write operation of the variable first occurs after the read operation of the variable , there “ Back ” It also refers to the chronological order .
  • Thread start rule (Thread Start Rule):Thread Object's start() Method occurs first in every action of this thread .
  • Thread termination rule (Thread Termination Rule): All operations in a thread occur first at the termination detection of this thread , We can go through Thread.join() Method end 、Thread.isAlive() The thread has been terminated .
  • Thread interrupt rule (Thread Interruption Rule): For threads interrupt() Method calls occur first when the interrupted thread's code detects the occurrence of an interrupt event , Can pass Thread.interrupted() Method detects if an interrupt has occurred .
  • Object termination rule (Finalizer Rule): Initialization of an object completed ( End of constructor execution ) What happened first finalize() The beginning of the method .
  • Transitivity (Transitivity): If you operate A First occurs in operation B, operation B First occurs in operation C, Then we can get the operation A First occurs in operation C Conclusion .

Minimalist practice cases

Java The language does not need any synchronization means to guarantee , The antecedent occurrence rule that can be established , That's all . The following is an example to illustrate how to use these rules to determine whether the operations are sequential , Is it thread safe .

private int value = 0;

public void setValue(int value){
    this.value = value;
}

public int getValue(){
    return value;
}

The above code is a set of very common getter/setter Method . Assuming that thread A and B, Threads A First ( The order of time ) Called setValue(1), After that thread B Calling... Of the same object getValue(), So thread B What is the return value received ?

Let's analyze the rules of antecedent principle in turn :

  1. First , Because the two methods are separated by threads A And thread B call , Not in a thread , So the procedural order rule doesn't apply here .
  2. next , Because there is no synchronization block , It doesn't happen naturally lock and unlock operation , So the tube lock rule doesn't apply .
  3. continue , because value Variables are not volatile Keyword modification , therefore volatile The variable rule does not apply .
  4. continue , Later threads start 、 End 、 Interruption rules and object termination rules have nothing to do with this .
  5. Last , Because there is no applicable antecedent rule , So there's no way to talk about the last transitivity .

therefore , Even if we know threads A Ahead of thread in operation time B, But we still can't determine the thread B getValue() method . let me put it another way , The operation in this is not thread safe .

Then how to fix this problem ?

We have at least two simpler options :

  1. The first one is , Or put getter/setter Methods are defined as synchronized Method , In this way, the pipe locking rules can be applied .
  2. The second kind , Or put value Defined as volatile Variable , because setter Method pair value The modification of does not depend on value Original value of , Satisfy volatile Keyword usage scenarios , In this way, you can apply volatile Variable rules to achieve antecedent relationships .

Through the above case , We know : An operation time occurs online , This does not mean that this operation will 「 Happen first 」. So if an operation 「 Happen first 」, Can we deduce that this operation must occur first in time ? Not really , Because it is possible to reorder instructions .

//  The following operations are performed in the same thread 
int j = 1;
int j = 2;

The above code is executed in the same thread , Execute the sequence rules according to the program ,int i = 1; The operation of occurs first in int j = 2;, but int j =2 The code may be executed by the processor first , Because they are not interdependent , It does not affect the correctness of the principle of first occurrence .

The above two cases together prove a conclusion : There is not much relationship between the sequence of time and the principle of first occurrence , So we should not be disturbed by the time sequence when we measure the concurrent security problems , Everything must be based on the principle of first occurrence .

summary

happens-before Principle shared 8 Article principle , It's right Java Simplification of memory model rules , Help programmers improve programming efficiency .

There is not much relationship between the sequence of time and the principle of first occurrence , When we measure concurrency security, we should not be disturbed by the time sequence , Everything must be based on the principle of first occurrence .

 In depth understanding of happens-before principle

原网站

版权声明
本文为[Chenshuyi]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/178/202206271037121653.html