In Java Concurrency in Practice one of the examples that I think surprises people (at least me) is something like this:
public class Foo {
private int n;
public Foo(int n) {
this.n = n;
}
public void check() {
if (n != n) throw new AssertionError("huh?");
}
}
The surprise (to me at least) was the claim that this is not thread safe, and not only it's not safe, but also there is a chance that the check method will throw the assertion error.
The explanation is that without synchronization / marking n as volatile, there is no visibility guarantee between different threads, and that the value of n can change while a thread is reading it.
But I wonder how likely it is to happen in practice. Or better, if I could replicate it somehow.
So I was trying to write code that will trigger that assertion error, without luck.
Is there a straight forward way to write a test that will prove that this visibility issue is not just theoretical?
Or is it something that changed in the more recent JVMs?
EDIT: related question: Not thread safe Object publishing
The use of audio and vibration in messaging apps is another common visibility of system status example. Short beeps, tings, and vibrations make users immediately aware of changes in the app.
For team members, visibility empowers them to be more efficient with their tasks and communication. When they have dashboards that let them see both their direct tasks and the bigger project picture, they feel more confident pushing a project forward. Without clarity, people can lose confidence or become unmotivated.
It serves to keep users informed of the current status and to allow them to steer the interaction in the right direction, without wasting effort. Such feedback can be as simple as a change of color once the user has clicked on a button, or a progress indicator when a process needs a little longer to finish.
But I wonder how likely it is to happen in practice.
Highly unlikely esp as the JIT can turn n
into a local variable and only read it one.
The problem with highly unlikely thread safety bugs is that one day, you might change something which shouldn't matter, like your choice of processor or JVM and suddenly your code breaks randomly.
Or better, if I could replicate it somehow.
There is not guarantee you can reproduce it either.
Is there a straight forward way to write a test that will prove that this visibility issue is not just theoretical?
In some cases, yes. but this one is a hard one to prove, partly because the JVM is not prevented from being more thread safe than the JLS says is the minimum.
For example, the HotSpot JVM often does what you might expect, not just the minimum in the docuemtation. e.g. System.gc() is only a hint according to the javadoc, but by default the HotSpot JVM will do it every time.
This scenario is VERY unlikely, but still possible. The thread would have to be paused in the very moment the first n
in the comparison is loaded, before the second one is and they are compared - and this takes so tiny a fraction of a second that you would have to be super lucky to hit it. But if you write this code in a super critical application that millions of users are going to use everyday, worldwide, it will happen sooner or later - it is only a matter of time.
There is no guarantee you can reproduce it - maybe it is even not possible on your machine. It depends on your platform, the VM, the Java compiler, etc...
You can convert the first n
into a local variable, then pause the thread (Sleep), and have second thread change the n before you do the comparison. But I thing this scenario would defeat the purpose of demonstrating your case.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With