Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding happens-before and synchronization [duplicate]

I'm trying to understand Java happens-before order concept and there are a few things that seem very confusing. As far as I can tell, happens before is just an order on the set of actions and does not provide any guarantees about real-time execution order. Actually (emphasize mine):

It should be noted that the presence of a happens-before relationship between two actions does not necessarily imply that they have to take place in that order in an implementation. If the reordering produces results consistent with a legal execution, it is not illegal.

So, all it says is that if there are two actions w (write) and r (read) such that hb(w, r), than r might actually happens before w in an execution, but there's no guarantee that it will. Also the write w is observed by the read r.

How I can determine that two actions are performed subsequently in run-time? For instance:

public volatile int v;
public int c;

Actions:

Thread A
v = 3;  //w

Thread B
c = v;  //r

Here we have hb(w, r) but that doesn't mean that c will contain value 3 after assignment. How do I enforce that c is assigned with 3? Does synchronization order provide such guarantees?

like image 479
St.Antario Avatar asked Apr 03 '16 09:04

St.Antario


People also ask

How do you explain synchronization?

Synchronization is the coordination of events to operate a system in unison. For example, the conductor of an orchestra keeps the orchestra synchronized or in time. Systems that operate with all parts in synchrony are said to be synchronous or in sync—and those that are not are asynchronous.

What is the happens before relationship?

In computer science, the happened-before relation (denoted: ) is a relation between the result of two events, such that if one event should happen before another event, the result must reflect that, even if those events are in reality executed out of order (usually to optimize program flow).

What is synchronization explain with example?

Synchronization in java is the capability to control the access of multiple threads to any shared resource. In the Multithreading concept, multiple threads try to access the shared resources at a time to produce inconsistent results. The synchronization is necessary for reliable communication between threads.


2 Answers

Here we have hb(w, r) but that doesn't mean that c will contain value 3 after assignment. How do I enforce that c is assigned with 3? Does synchronization order provide such guarantees?

And your example

public volatile int v;
public int c;
Actions:

Thread A
v = 3;  //w

Thread B
c = v;  //r

You don't need volatile for v in your example. Let's take a look at a similar example

int v = 0;
int c = 0;
volatile boolean assigned = false;

Actions:

Thread A

v = 3;
assigned = true;

Thread B

while(!assigned);
c = v;
  1. assigned field is volatile.
  2. We will have c = v statement in Thread B only after assigned will be true (while(!assigned) is responsible for that).
  3. if we have volatile — we have happens before.
  4. happens before means that, if we see assigned == true — we will see all that happened before a statement assigned = true: we will see v = 3.
  5. So when we have assigned == true -> we have v = 3.
  6. We have c = 3 as a result.

What will happen without volatile

int v = 0;
int c = 0;
boolean assigned = false;

Actions:

Thread A

v = 3;
assigned = true;

Thread B

while(!assigned);
c = v;

We have assigned without volatile for now.

The value of c in the Thread B can be equal 0 or 3 in such situation. So there is not any guaranties that c == 3.

like image 37
v.ladynev Avatar answered Nov 03 '22 09:11

v.ladynev


When the JLS says that some event X in thread A establishes a happens before relationship with event Y in thread B, it does not mean that X will happen before Y.

It means that IF X happens before Y, then both threads will agree that X happened before Y. That is to say, both threads will see the program's memory in a state that is consistent with X happening before Y.


It's all about memory. Threads communicate through shared memory, but when there are multiple CPUs in a system, all trying to access the same memory system, then the memory system becomes a bottleneck. Therefore, the CPUs in a typical multi-CPU computer are allowed to delay, re-order, and cache memory operations in order to speed things up.

That works great when threads are not interacting with one another, but it causes problems when they actually do want to interact: If thread A stores a value into an ordinary variable, Java makes no guarantee about when (or even if) thread B will see the value change.

In order to overcome that problem when it's important, Java gives you certain means of synchronizing threads. That is, getting the threads to agree on the state of the program's memory. The volatile keyword and the synchronized keyword are two means of establishing synchronization between threads.


I think the reason they called it "happens before" is to emphasize the transitive nature of the relationship: If you can prove that A happens before B, and you can prove that B happens before C, then according to the rules specified in the JLS, you have proved that A happens before C.

like image 142
Solomon Slow Avatar answered Nov 03 '22 10:11

Solomon Slow