I am aware of the next scenario: (Weird formatting, I know)
private final AtomicBoolean aBoolean = new AtomicBoolean(true);
public void doSomething() {
if (
aBoolean.get() // line A
&& // line B
aBoolean.compareAndSet(true, false) // line C
) {
System.out.println("Was true!")
}
}
If thread #1 and thread #2 enter doSomething()
at exactly the same time this will happen:
Thread #1 and thread #2 will read
aBoolean.get()
as being == "true" simultaneously.Both will execute the "&&" operator.
CMPXCHG instruction kicks in for both threads simultaneously:
3.1 LOCK prefix is used natively
3.2 Either thread #1 or #2 arrives first, winning the race.
3.3 Winning thread compares (is aBoolean == true ?) this will return "true", hence aBoolean will be set to "false".
3.4 aBoolean is now false.
3.5 Losing thread compares (is aBoolean == true ?) this will return "false", hence short-circuiting any further operations.
winning thread will print "Was true!".
Under the perspective of the "losing" thread the first aBoolean.get()
in "line A" was .... let's say... a "lie".
Now under the assumption that executions can happen in between operators, as it just did in the example above, let's add a second method for a second scenario:
public void unluckySet() {
aBoolean.set(false);
}
Let's say Thread #3 just so happens to arrive and execute unluckySet()
at precisely the exact moment that our "winning thread" arrived at "line B" where the "&&" is executing.
If winning thread went as far as to reach "line B" it means it reached "line A" with aBoolean being "true".
My questions are:
Will CMPXCHG read the updated value correctly as being "false"?, meaning the .set()
is also held by the same lock as the compareAndSet()
.
In concurrency and between threads:
Do operators ("&&", "||", "==", "=", maybe even "return;"??) happen at any nano second, OR are they interleaved with executions (";") so that both END in an interleaved manner, preventing possible collisions?