Visibility orderliness, Happens-before to get


An article on the source of three concurrent Bug, please keep your eyes open to see that they talked about the visibility / atomic / ordering three issues, which are usually contrary to our intuition and thinking patterns, and it leads many concurrent Bug

    In order to solve the short-board CPU, memory, IO, increasing the cache, but this led to a visibility problem

    The compiler / processor without optimization (Java code is compiled into Java bytecode will, bytecode classes loaded into the JVM, JVM byte code execution, must be transformed into the final assembly instruction executed on the CPU) , resulting in ordering problem

The original intention is good, but raises new problems, the most effective way to disable caching and compiler optimization, although the problem can be resolved, but “back to the original starting point, just stood before the mirror,” is very embarrassing, we the performance of the program on worrying.


    As we do not want to write a program ape bug affecting KPI, so I hope the memory model is easy to understand, easy to program. This requires a strong memory-based model to write code

    As compilers and processors do not want outsiders to deal with it is very slow, so I hope they are bound by the better memory model can be optimized without authorization by them, which requires a weak memory model

As the saying goes: “There is nothing that can not be solved by a meeting, if there is, then open again” ?

JSR-133 experts have a new idea, since it can not completely prevent caching and compiler optimization, then disable the cache on demand and compiler optimization, demand is to add some constraints, including constraints on the simple mention an article the main contents of visited volatile, synchronized, final three keywords, as well as the principles Happens-Before you might have heard of (include constraints visibility and orderliness), Happens-before rule also chapter

In order to meet the strong demand of both, to take care of both sides of the emotional reason that: JMM procedures ape said to a white lie: “Happpen-Befores will strictly abide by the rules, will not reorder” the program to ape assured, but in private It has its own strategy:

    Reordering the results will change for the program, JMM requires compilers and processors must prohibit such reordering.

    Reordering will not change the result of execution for the program, JMM compiler and processor not required (this allows reordering JMM).

Let’s use a diagram to explain:

This is the good faith lie, although it is a lie, but still takes care of the interests of the program apes, so we only need to know happens-before rules can be guaranteed (pictures for a long time, do not know if the lies ?, welcome to leave a message)


Happens-before regular operation is mainly used to constrain the two, having a relationship between two happens-before operation, does not mean that a prior operation must be performed prior to an operation after the former requires only happens-before operation (performed results) after a visible operation, (the first is visible to and ordered before the second)

Having said that, first look at a piece of code takes you step by step into the Happen-Befores principle, to see how to use this principle to solve the problem of visibility and order:

class ReorderExample {
  int x = 0;
  boolean flag = false;
  public void writer() {
    x = 42;    //1
    flag = true;    //2
  public void reader() {
    if (flag) { //3
      System.out.println(x);    //4

A thread of execution is assumed writer method, B reader thread execution method, printed x may be 0, the article described: Because the code 1 and 2 there is no data dependencies, it may be reordered

flag = true;    //2
x = 42;    //1

Therefore, the thread A flag = true when x is written but not reassigned thread B may have been printed x is 0

So try to flag plus the volatile keyword:

volatile boolean flag = false;

Even adding the volatile keyword, this problem is not resolved before java1.5, but java1.5 and after the volatile version of its semantic enhancements made, the problem is resolved, which is inseparable from Happens-before rule constraints a total of six rules, let me see

Program sequence rules

Each operation of one thread, happens-before any subsequent operations on the thread
    The first principle is a feeling in the ideal state of “nonsense”, and the above-mentioned circumstances and will reordering appear contradictory, note that this is a thread operation, in fact, implies “as-if- serial “semantic: it means as long as the results will not be changed, no matter how” Sort “, is right

This rule is a basic rule, happens-before rule is multi-threaded, so to other rules and constraints together in order to reflect its sequential nature, do not worry, continue to look down

volatile variable rules

Writing to a volatile domain, happens-before reading of the volatile domain in any subsequent

I will add two lines of code above program stated:

public class ReorderExample {

    private int x = 0;
    private int y = 1;
    private volatile boolean flag = false;

    public void writer(){
        x = 42; //1
        y = 50; //2
        flag = true;    //3

    public void reader(){
        if (flag){  //4
            System.out.println("x:" + x);   //5
            System.out.println("y:" + y);   //6

Here related to the volatile memory enhancement semantics, first look at the tables:

Can reordering

The second operation

The second operation

The second operation

The first operation

Normal read / write

volatile read

volatile write

Normal read / write

volatile read

volatile write


From the last one can be seen in this table:

If the second operation is a volatile write, no matter what is the first operation that can not be reordered, which ensures that the volatile write operation before will not be reordered to write after volatile
    Take the above code, the code 1 and 2 will not be reordered to the back 3 of the code, but the code 1 and 2 may be reordered (not depend not affect the execution result), and here comes sequential procedures rules are not already linked up already?

From the second to last row of this table it can be seen:

If the first operation is a volatile read, no matter what the second operation is, it ensures that operations after volatile read are not reordered before volatile read
Take the above code, code 4 is to read volatile variables, code 5 and 6 will not be reordered before code 4

Achieve volatile memory semantics is applied to the “memory barrier” because it totally alone enough to write a chapter here in order not to obscure the protagonist Happens-before aura, maintaining an understanding of the continuity Happens-before, do not do too much to explain

Here, look at this rule, seemingly did not solve what problem, because it also joint third rule only works

Transfer rules

If A happens-before B, and B happens-before C, then A happens-before C
    Directly on the map at the example described above

As can be seen from FIG.

    x = 42 and y = 50 Happens-before flag = true, it is the rule 1

    Write variable (Code 3) flag = true Happens-before read variable (Code 4) if (flag), which is the rule 2

The transfer rules Rule 3, x = 42 Happens-before read variable if (flag)

Mystery to be unveiled: If the thread B reads the flag is true, then x = 42 and y = 50 thread B will certainly be seen, this is enhanced Java1.5 of (the previous version could be written ordinary variables and writing volatile variables reordering)

Usually three rules above, is a joint constraint, here you understand? Rules not finished, continue to look

Monitor lock rules

A lock for unlocking happens-before subsequent lock this lock

This rule, I think you should be most familiar with, it is to explain the synchronized keyword, view

public class SynchronizedExample {
    private int x = 0;

    public void synBlock(){
        // 1.加锁
        synchronized (SynchronizedExample.class){
            x = 1; // 对x赋值
        // 3.解锁

    // 1.加锁
    public synchronized void synMethod(){
        x = 2; // 对x赋值
    // 3. 解锁

First obtain a lock thread releases the lock on the assignment after x, and then get another lock, will be able to see the changes to the assignment x, it is so simple, please see above junior partner program with the following command, and look sync block synchronization methods are converted into assembly instructions What is the difference?

javap -c -v SynchronizedExample

This is related to synchronized semantics, small partners can first understand their own, the contents of the lock will be explained in detail

start () rule

That is, the main thread after thread B A promoter thread A if performing operations ThreadB.start () (start thread B), then A thread ThreadB.start () operation in any of the following happens-before thread B, B sub-thread can be seen in operation before the main thread promoter thread B, look at a program on the second understand

public class StartExample {
    private int x = 0;
    private int y = 1;
    private boolean flag = false;

    public static void main(String[] args) throws InterruptedException {
        StartExample startExample = new StartExample();

        Thread thread1 = new Thread(startExample::writer, "线程1");
        startExample.x = 10;
        startExample.y = 20;
        startExample.flag = true;



    public void writer(){
        System.out.println("x:" + x );
        System.out.println("y:" + y );
        System.out.println("flag:" + flag );

operation result:


Process finished with exit code 0

Thread 1 saw the results of all assignments before the main thread calls thread1.start (), there is no print “main thread ends,” You know why? This daemon thread related knowledge

join () rule

If thread A executes operations ThreadB.join () returns successfully, then any of the following happens-before thread B to the thread A in the () operation successful return from ThreadB.join, rules and start the contrary, the main thread wait for the child thread B A complete, when the child thread B is completed, the main thread can see the assignment of sub-thread B, the program will make a small change, you will know in seconds

public class JoinExample {
    private int x = 0;
    private int y = 1;
    private boolean flag = false;

    public static void main(String[] args) throws InterruptedException {
        JoinExample joinExample = new JoinExample();

        Thread thread1 = new Thread(joinExample::writer, "线程1");


        System.out.println("x:" + joinExample.x );
        System.out.println("y:" + joinExample.y );
        System.out.println("flag:" + joinExample.flag );

    public void writer(){
        this.x = 100;
        this.y = 200;
        this.flag = true;

operation result:


Process finished with exit code 0

“The main thread ends,” the words printed out myself, and still have a relationship when the thread exits

to sum up

    Happens-before focusing on solving a front operating results for a visible operation, I believe that here, you already know about Happens-before rules that solve the visibility and multi-threaded programming of ordering problem, but has not completely solve the problem of atomicity (except synchronized)

    One way to start and join rule was also the main thread to communicate with the child thread

    From the perspective of memory semantics, volatile write-read and lock release have the same memory effect; volatile write and lock release have the same memory semantics; volatile read have the same memory semantics as lock acquisition, ⚠️⚠️⚠️ (knocking on the blackboard) volatile solves the visibility problem. Synchronisation solves the problem of atomicity, which is definitely not the same thing, and subsequent articles will also explain

Additional information

    Access personal blog find more exciting advance

    Multithreading series as a whole will follow my outline rhythm to write, but if you have any doubt, welcome to multithreading series of questions I alone establish message articles message summary, I would be a unified response, many if common questions, I will insert the relevant chapters do explain alone

    Related tags and send the article, I will be synced to the code base, the public number reply “demo”, click on the link, you can find concurrency subprojects

    If the article helpful, please forward the small partners to share more of your friends, we progress together

Soul questioning

    Sync block synchronization methods and what is the difference in the compiled CPU instruction?

    Thread has Daemon (Daemon threads) and non-Daemon thread, the thread exit strategy you know it?

    What other doubts do you have about Happens-Before?

Improve productivity tools

MarkDown Form Builder

Many forms of this paper is pasted from the official website, how to convert it directly into the MD table it? So can help you, whether it is generated MD table, table or paste content generation and content are excellent, of course, more than MD table, you have found it, more tools, public No. reply “tools” get

Recommended Reading

    Every day SpringBoot, still do not understand RESTful API returns a unified data format is how to achieve?

    Parents delegation model: manufacturers of high-frequency interview questions, easy to get

    Interview not know the difference between BeanFactory and the ApplicationContext?

    How to design a good RESTful API

  • Red-black tree, super movement chart Detailed, easy to understand

Welcome to continued public concern number: “arch day a soldier.”

    Dry cutting-edge Java technology sharing

    Productivity tools summary | Reply “Tools”

    Analysis of interview questions and answers

    Technical Data collection | Reply “Information”

Easy to read detective novels thinking fun learning Java technology stack-related knowledge, in line with the simplification of complex issues, problems specific abstract and graphical decomposition of the principle of progressive technical issues, technology continues to update, please stay tuned ……

Leave a Reply