Blood cases caused by Java Memory Model

Source: Internet
Author: User

Okay, I have a title.

 

Previous blog

I mentioned the Java Memory Model briefly, but this time I encountered an error due to the characteristics of jmm.

The background is that a nullpointerexception is thrown during the stress test of the system. This is strange, because I have been running a stress test for a long time, but this will inexplicably report an error, so I found the corresponding code line, as shown below:

 

Thread

This. data = new data (); <br/> synchronized (this) {</P> <p> This. isdone = true; <br/> This. Y () ;}< br/>

 

Thread B

Synchronized (this) {<br/> If (this. isdone) {<br/>}else {<br/> This. wait (); <br/>}< br/> This. data. do (); // throw nullpointerexception <br/>

 

The above two sections of code have different thread executions. If it is executed normally, this nullpointerexception cannot be thrown, because in the code block of thread A, this. Data has been assigned a value before this. Every y () is called. The only explanation is that the execution sequence of the code block of thread a is disrupted. According to the jmm specification, the execution sequence of program code is not necessarily guaranteed. Here, "this. data = new data (); "this statement may be executed after Synchronized (), so when thread B starts from this. this. if data has not been assigned a value, an error is thrown.

 

The correct code is also very simple. Put the line "This. Data = new data ();" into synchronized:

 

Thread

Synchronized (this) {<br/> This. data = new data (); <br/> This. isdone = true; <br/> This. Y () ;}< br/>

 

Because the synchronized keyword is used, the execution result of the Code in synchronized can be seen before other threads enter synchronzied. Here, it is guaranteed that when the thread enters the synchronized code, "This. Data = new data ();" in thread a has been executed.

 

-- End --

 

-------------------------- Gorgeous split line --------------------------------


I would like to add: (because this article has been recommended, in order not to miss people ...)


Comment, roamm

Synchronzied may provide the memory barrier effect. So far, this is still inconclusive. I posted this question to the Java version of smth today, but it seems that there is no final result in the discussion.


This problem can be simply summarized:

For a piece of code

A

B

C

There is a possibility of execution in disorder: (for example, the actual execution order is C-> B->)


Then, modify the code.

A

Synchronzied {B}

C

Whether there is still possibility of execution in disorder (for example, C-> synchronzied {B}->)


There is no conclusion. (It should be said that no evidence can be found to prove that synchronized provides effects similar to memory barrier)

 

-------------------------------- Lili split line --------------------------------------------------


There are basically answers to this question. Repeat it.

Examples:

Public class test {<br/> int x = 0, y = 0; <br/> int A = 0, B = 0; <br/> Public void task1 () {<br/> A = 1; <br/> X = B; <br/>}< br/> Public void task2 () {<br/> B = 1; <br/> Y = A; <br/>}< br/>

Assume that a test instance has two threads that execute Task 1 (thread a) and Task 2 (thread B) respectively ).
Because there is no synchronization between the two threads, multiple executions may occur. But more specifically, due to JVM optimization, there may be disorder, so there may be:
Thread A: x = B -------------------------------------------> A = 1
Thread B: -----------> B = 1 -------> Y = ---------------------
Finally, x = 0, y = 0
I will not talk about this.


The problem now is that if you change the code:

Public class test {<br/> int x = 0, y = 0; <br/> int A = 0, B = 0; <br/> Public void task1 () {<br/> A = 1; <br/> synchronized (this) {<br/> X = B; <br/>}< br/> Public void task2 () {<br/> synchronized (this) {<br/> B = 1; <br/>}< br/> Y = A; <br/>}< br/>


Then, is it possible that:
Thread A: Synchronized {x = B;} ---------------------------------------------------------------> A = 1
Thread B: --------------------------------------------> synchronized {B = 1;} --> Y = ----------


The conclusion is impossible.



Java concurrency in practice 3.1.3 contains the following section:

When thread a executes a synchronized block, and subsequently thread B enters a synchronized block guarded by the same lock, the values of variables that were visible to a prior to releasing the lock are guaranteed to be visible to B upon acquiring thelock.

In other words, everything a didIn or prior to a synchronized Block
Is visible to B when it executes a synchronized block guarded by the same lock. Without synchronization, there is no such guarantee.

.......

Locking is not just about mutual exclusion; it is also about memory visibility.


This means that if thread a enters the synchronized area and thread B goes on, when thread B obtains the lock, the synchronized area of thread a and the execution results of the previous Code are visible to thread B ,:


In our example, assume that thread a is executed first and enters the synchronized area first. When thread B enters the synchronzied area and is ready to execute B = 1, the JVM ensures that thread a's
Synchronized (this) {x = B ;}
This code execution effect is visible to thread B, not only that, but the code before connecting to the synchronzied Area
A = 1;
It must also be visible. Therefore, if thread a first enters the synchronized area, it can only be:

Thread A: Synchronized {x = B;} ----> A = 1 ------------------------------------------------------
Thread B: -------------------------- -----------------------> synchronized {B = 1 ;}----> Y = ---

Or

Thread A: a = 1 ----> synchronized {x = B ;}--------------------------------------------------------
Thread B: ----------------------------------------------------> synchronized {B = 1;} ----> Y = ---

Their results are x = 0, y = 1.


With this conclusion, let's go back to the example I reported a bug at the beginning of this article. It can be seen that the nullpointexception is not caused by the so-called "disordered execution". It should be that the program is not written somewhere else. Therefore, the so-called "Blood cases caused by Java Memory Model" is not true. (You may not be able to watch the official website ....)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.