Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What does reordering have to do with happens-before

2025-02-24 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article introduces the relevant knowledge of "what is the relationship between reordering and happens-before". In the operation of actual cases, many people will encounter such a dilemma, so let the editor lead you to learn how to deal with these situations. I hope you can read it carefully and be able to achieve something!

For instance

Before we talk about reordering, let's look at an example:

Int a = 0, b = 0; public void methodOne () {int one = a; b = 1;} public void methodTwo () {int two = b; a = 2;}

It should be easy to see that in the above example, I defined two shared variables an and b, as well as two methods. The first method is to assign the local variable one to an and then set b to 1. The second method is to assign the local variable two to b and then set the value of a to 2.

So I have a question here, what is the value of (one, two)?

You may tell me either (0,1) or (2,0) without thinking, depending on which method method my main method executes first.

Yes, if the program runs on a single thread, there is nothing wrong with this answer.

But what if it's in a multithreaded environment?

Suppose that methodOne and methodTwo are now executed on two different threads, and the Java virtual machine switches threads after executing the first assignment statement of either method, and the value of (one, two) at this time may be (0,0)

Do you have any doubts when you see this? Why, how come the program I wrote is good, and when it comes to the Java virtual machine, it changes for me?

It is because of the reordering that occurs during execution. It may be a reorder of the just-in-time compiler, a disordered execution of the processor, or a reorder of the memory system.

In short, reordering occurs during program execution, and the result may be (0,0).

Why is it reordered?

After reading the above, you may have questions, why is there a reordering?

There is no problem for my program to be written down according to my own logic. Why does the Java virtual machine move my program logic?

If you think about it, CPU and memory are all very valuable resources. If the Java virtual machine has no effect after reordering, it certainly won't do such a thankless thing.

So what are the benefits of reordering?

Reordering improves the performance of the program.

In order to make it easier to understand, I will take the scene in life as an example.

When you get up early in the morning, you can dress, wash, cook and eat, right? So what do you do after you get up? When you wash, do you first cook the rice (for example, let the egg steamer steam an egg for you), and then, after you finish washing, you can have breakfast directly?

Why are you doing this? In order to save time, you can sleep for one more minute. Is that right?

By the same token, the reason why Java virtual machines are reordered is to improve program performance. The program you write, a simple single line of code, to the bottom may need to use different hardware, such as an instruction needs to use both CPU and printer equipment, but at this time the task of CPU is completed, the task of the printer is not finished, what to do at this time? Don't let CPU execute the next instructions? CPU's time is so precious that you don't let it work, are you sure you're not wasting its life?

So in order to improve the utilization and the performance of the program, the Java virtual machine executes another instruction before your instruction is fully executed. This is the pipeline technology.

What does the assembly line fear most? I am the one who carried out the command, suddenly interrupted, and the cost of resuming the interruption is very high, so we have to try our best not to let the interruption happen.

Instant compiler reordering, processor out-of-order execution, and memory system reordering all exist to reduce interrupts.

At this point, do you know anything about reordering Java virtual machines?

Problems caused by reordering

Going back to the example given at the beginning of the article, reordering improves the utilization of CPU and the performance of the program, but the result of my program may be wrong, isn't it a little too much for the loss?

Because reordering can guarantee serial semantic consistency, but there is no obligation to ensure semantic consistency between multithreads.

There is a way to solve all problems. If not, think again.

How does it solve it? We need to talk about sequential consistent memory model and JMM (Java Memory Model, Java memory model).

Sequential consistent memory Model and JMM

If you want to talk about data consistency, you have to talk about data competition.

What is data competition? The definition is given in the Java memory model specification:

Write a variable in a thread

Read the same variable in another thread

Write and read are not sorted by synchronization

When the code contains data competition, the execution result of the program is often beyond your imagination, such as the example we just talked about, the result may be (0,0). But if a multithreaded program can synchronize correctly, the above results will not appear.

The Java memory model guarantees the memory consistency of correctly synchronized multithreaded programs as follows:

If the program is synchronized correctly, the execution of the program will also be sequentially consistent, that is, the execution result of the program is the same as that of the program in the sequential consistency model.

This synchronization includes the use of volatile, final, synchronized and other keywords to achieve multi-threaded synchronization. That is to say, if these synchronizations are not used correctly, JMM will not have a guarantee of memory visibility, which will lead to errors in the program written.

The sequential consistency memory model is an ideal theoretical reference model, which provides programmers with a strong memory visibility guarantee. The sequential consistency model has two characteristics:

All operations in a thread must be performed in the order of the program (that is, in the order in which the code is written)

Regardless of whether the program is synchronized or not, all threads can only see a single order in which operations are executed. That is, in the sequential consistency model, each operation must be atomic and immediately visible to all threads.

As mentioned above, the sequential consistent memory model is an ideal theoretical reference model, because the sequential consistent memory model requires operations to be visible to all threads, which alone degrades the performance of the Java virtual machine. JMM makes some optimizations based on the sequentially consistent memory model:

For synchronous multithreaded programs, that is, the code in the critical zone, JMM allows reordering (but does not allow the code in the critical zone to "escape" outside the critical area, because if allowed, it will break the memory semantics of the lock)

For unsynchronized multithreaded programs, JMM provides only minimal security: the value read by a thread is either a value written by a previous thread or a default value, and does not make up for nothing.

It should be felt that JMM gives compilers and processors some space compared to the sequential consistent memory model, allowing them to reorder.

At this point, there is a conflict: programmers need JMM to provide a strong memory model to write code, that is, the order in which my code is written, the program will be executed; but compilers and processors need less JMM constraints on them, so that they can do as much optimization as possible to improve performance.

As an intermediary of JMM, to meet not only the needs of programmers, but also the needs of compilers and processors, it is necessary to find a balance between the two, so that the code written by programmers can produce the desired results, and at the same time, compilers and processors can do some optimizations.

JMM's solution is: for programmers, provide happens-before rules, so as to meet the needs of programmers-> easy to understand, and provide a strong enough memory visibility guarantee; for compilers and processors, as long as they do not change the execution results of the program (provided that multithreaded programs are synchronized correctly), they can optimize as much as they want.

Happens-before

Finally, I'm talking about happens-before.

Let's first look at the definition of the happens-before relationship:

If one operation happens-before another operation, the execution result of the first operation is visible to the second operation.

If there is a happens-before relationship between the two operations, it does not mean that the specific implementation of the Java platform must be performed in the order specified by the happens-before relationship. If the result of the reordered execution is consistent with the result executed according to the happens-before relationship, then JMM also allows such a reorder.

Seeing this, do you think that this is the same as the semantics of as-if-serial? Yes, happens-before relationships are essentially the same thing as as-if-serial semantics.

As-if-serial semantics ensures that the execution result after reordering in a single thread is consistent with that of the program code itself, and the happens-before relationship ensures that the execution results of correctly synchronized multithreaded programs will not be changed by reordering.

To sum up: if operation A happens-before operation B, then what operation A does in memory is visible to operation B, whether they are in the same thread or not.

In Java, for happens-before relationships, there are the following rules:

Program order rules: each operation in a thread, happens-before any subsequent operations in that thread

Monitor lock rule: unlock a lock, which is subsequently locked by happens-before

Volatile variable rules: write to a volatile domain, happens-before and any subsequent reads to the volatile domain

Transitivity: if A happens-before B and B happens-before C, then A happens-before C

Start rule: if thread An executes the operation ThreadB. Start () starts thread B, then thread A's ThreadB. Start () any operation happens-before in thread B

Join rule: if thread An executes the operation ThreadB. Join () and returns successfully, then any operation in thread B happens-before on thread A from ThreadB. The join () operation returned successfully.

This is the end of the content of "what does reordering have to do with happens-before"? thank you for reading. If you want to know more about the industry, you can follow the website, the editor will output more high-quality practical articles for you!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report