Making this visibility example fail - java

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

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 a Foo is published unsafely, theoretically another thread could observe two different values when it reads n twice.
The following program could fail because of that reason.
public static Foo shared;
public static void main(String[] args)
{
new Thread(){
#Override
public void run()
{
while(true)
{
Foo foo = shared;
if(foo!=null)
foo.check();
}
}
}.start();
new Thread(){
#Override
public void run()
{
while(true)
{
shared = new Foo(1); // unsafe publication
}
}
}.start();
}
However it's almost impossible to observe that it fails; VM likely optimizes n!=n to false without actually reading n twice.
But we can show an equivalent program, i.e. a valid transformation of the previous program as far as Java Memory Model is concerned, and observe that it fails immediately
static public class Foo
{
int n;
public Foo()
{
}
public void check()
{
int n1 = n;
no_op();
int n2 = n;
if (n1 != n2)
throw new AssertionError("huh?");
}
}
// calling this method has no effect on memory semantics
static void no_op()
{
if(Math.sin(1)>1) System.out.println("never");
}
public static Foo shared;
public static void main(String[] args)
{
new Thread(){
#Override
public void run()
{
while(true)
{
Foo foo = shared;
if(foo!=null)
foo.check();
}
}
}.start();
new Thread(){
#Override
public void run()
{
while(true)
{
// a valid transformation of `shared=new Foo(1)`
Foo foo = new Foo();
shared = foo;
no_op();
foo.n = 1;
}
}
}.start();
}

Related

Unexpected thread behavior. Visibility

I have the following code:
public static boolean turn = true;
public static void main(String[] args) {
Runnable r1 = new Runnable() {
public void run() {
while (true) {
while (turn) {
System.out.print("a");
turn = false;
}
}
}
};
Runnable r2 = new Runnable() {
public void run() {
while (true) {
while (!turn) {
System.out.print("b");
turn = true;
}
}
}
};
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
t1.start();
t2.start();
}
In class we've learned about "Visibility" problems that may occur when using un-synchronized code.
I understand that in order to save time, the compiler will decide the grab turn to the cache in the CPU for the loop, meaning that the thread will not be aware if the turn value was changed in the RAM because he doesn't check it.
From what I understand, I would expected the code to run like this:
T1 will see turn as true -> enter loop and print -> change turn to false -> gets stuck
T2 will think turn hasn't changed -> will get stuck
I would expect that if T1 will start before T2: only 'a' will be printed and both threads will run in an infinite loop without printing anything else
However, when I'm running the code sometimes I get a few "ababa...." before both threads will stuck.
What am I missing ?
EDIT:
The following code does what I expect it: the thread will run in a infinite loop:
public class Test extends Thread {
boolean keepRunning = true;
public void run() {
long count = 0;
while (keepRunning) {
count++;
}
System.out.println("Thread terminated." + count);
}
public static void main(String[] args) throws InterruptedException {
Test t = new Test();
t.start();
Thread.sleep(1000);
t.keepRunning = false;
System.out.println("keepRunning set to false.");
}
}
How are they different from each other ?
When I run the code, sometimes I get a few "ababa...." before both threads will stuck.
I suspect that what is happening is that the behavior is changing when the code is JIT compiled. Before JIT compilation the writes are visible because the interpreter is doing write-throughs. After JIT compilation, either the cache flushes or the reads have been optimized away ... because the memory model allows this.
What am I missing ?
What you are missing is that you are expecting unspecified behavior to be consistent. It doesn't have to be. After all, it is unspecified! (This is true, even if my proposed explanation above is incorrect.)
The fact that turn isn't volatile doesn't mean that your code WILL break, just that it MIGHT break. For all we know, the thread could see false or true at any given moment. Caches could just be randomly flushed for no reason in particular, the thread could retain its cache, etc etc.
It could be because your code is experiencing side effects from System.out.print, which internally writes to a synchronized method:
521 private void write(String s) {
522 try {
523 synchronized (this) {
(Source - DocJar)
The memory effects of synchronized could be flushing the cache and therefore impact your code.
As #Stephen C said, it could also be the JIT, which might hoist the boolean check because it assumes that the value can't change due to another thread.
So out of the three different possibilities mentioned so far, they could all be factors to contribute to how your code behaves. Visibility is a factor, not a determiner.

Should I synchronize method in my example?

I'm not sure if I should synchronize method methodOne() in my example. I think not but I'm not 100% sure. Could you please give me advice what to do?
public class SynchroIssue {
class Test {
private double a = 0;
void methodOne() {
a++;
}
void go() {
new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i < Integer.MAX_VALUE; i++) {
methodOne();
System.out.println(Thread.currentThread().getName() + ", a = " + a);
}
}
}).start();
}
}
public static void main(String... args) {
SynchroIssue mainObj = new SynchroIssue();
SynchroIssue.Test object1 = mainObj.new Test();
SynchroIssue.Test object2 = mainObj.new Test();
object1.go();
object2.go();
}
}
Assuming that you are actually going to use instances of the SynchroIssue class concurrently, which you are not doing currently, the answer is yes.
The increment operator is not atomic. It is actually 3 instructions:
Get the current value.
Add 1 to that.
Store new value.
If you are not synchronized, concurrent threads can overlap those steps resulting in strange behavior.
Another option, if you are truly only interested in integers, would be the use of AtomicInteger, which has methods to atomically increment.
object1 and object2 are different objects, each start only one thread, and the variable "a" is private and not static, so "a" are different objects too, and there is no interaction between threads. So there is no need to synchronise methodOne().
In this specific example there's no value to be gained by synchronising the methods because only a single thread ever actually interacts with a given instance.
If you called object1.go() twice you'd have a problem. Using synchronized would not be the best solution to that problem though, you should instead use a java.util.concurrent.atomic.DoubleAccumulator, although AtomicInteger would function just as well given that you start at 0 and only ever increment by 1.
In general, you should be wary of using synchronized to roll your own synchronisation protocols. Prefer instead known thread-safe classes where they're available. java.util.concurrent is a good place to look.
You should, but it wouldn't solve your problem.
If you would synchronize the method, only one thread would be able to increase the variable at a time. But the following System.out.println could still print another value, since by the time you call it, another thread may already have increased a.
The solution for your problem would be, that methodOne would also have to return the variable. Something like this:
synchronized double methodOne() {
return ++a;
}
And the thread should do:
for (int i = 0; i < Integer.MAX_VALUE; i++) {
System.out.println(Thread.currentThread().getName() + ", a = " + methodOne());
}
EDIT: as others already pointed out, you only have to do this if you intend to make the variable static. Otherwise you can leave your code as it is.
I want to add some hints to Brett Okken's answer:
Most of the times, when you have a member variable in your class which is modified by the methods of your class in a concurrent context by more than one thread, you should think about one of the synchronization scopes.
Always go for the smallest available scope of synchronization.
Hope this would be helpful.

Does making variable volatile get rid of: Multithreaded correctness - Inconsistent synchronization

I'm getting Inconsistent synchronization error on sonar on following code.
public int getMessageCount()
{
return m_messageCount;
}
public void onMessage(XQMessage msg) throws XQServiceException
{
synchronized(this)
{
m_messageCount--;
// add the message to the result
m_messages.add(msg);
if (m_messageCount == 0)
{
// wake up client
finished();
}
}
}
Error is on "return m_messageCount". If i make m_message volatile, will it solve the issue?
#jameslarge Can you give this AtomicInteger suggestion in separate post
I was thinking, something like this:
static final int INITIAL_MESSAGE_COUNT = ...;
AtomicInteger messageCount = new AtomicInteger(INITIAL_MESSAGE_COUNT);
public int getMessageCount()
{
return messageCount.get();
}
public void onMessage(XQMessage msg) throws XQServiceException
{
int mc = messageCount.decrementAndGet();
messages.add(msg);
if (mc == 0) wake_up_client();
}
NOTE: the messages.add() call is inside a synchronized block in your implementation. That is no longer the case in my version. I don't know what messages is exactly, but if you were relying on the synchronized block to protect it, you will have to add synchronization back in. At that point you might as well just go with your original version: AtomicInteger is more complicated than just using a regular int. I don't use it except when it allows me to implement some algorithm without using synchronized blocks.
P.S.; What is supposed to happen if the message count is already zero when onMessage() is called? Can that happen? If it happens, you'll get a negative message count. I don't have enough information to know whether that would be a good thing or a bad thing.
P.P.S.; What about that XQServiceException? Both of our implementations will decrement the message count regardless of whether or not messages.add() throws an exception. That might not be what you want. I don't know.
Since you are using synchronized(this) when you modify m_messageCount you can make the getMessageCount() method synchronized and that will solve your problem.
For example:
public synchronized int getMessageCount(){
return m_messageCount;
}

why is this thread safe?

Because it always prints out '3'. No synchronization needed? I am testing this simple thing because I am having a trouble in a real multiple thread problem, which isn't good to illustrate the problem, because it's large. This is a simplified version to showcase the situation.
class Test {
public static int count = 0;
class CountThread extends Thread {
public void run()
{
count++;
}
}
public void add(){
CountThread a = new CountThread();
CountThread b = new CountThread();
CountThread c = new CountThread();
a.start();
b.start();
c.start();
try {
a.join();
b.join();
c.join();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
public static void main(String[] args) {
Test test = new Test();
System.out.println("START = " + Test.count);
test.add();
System.out.println("END: Account balance = " + Test.count);
}
Because it always prints out '3'. No synchronization needed?
It is not thread safe and you are just getting lucky. If you run this 1000 times, or on different architectures, you will see different output -- i.e. not 3.
I would suggest using AtomicInteger instead of a static field ++ which is not synchronized.
public static AtomicInteger count = new AtomicInteger();
...
public void run() {
count.incrementAndGet();
}
...
Seems to me like count++ is fast enough to finish until you invoke 'run' for the other class. So basically it runs sequential.
But, if this was a real life example, and two different threads were usingCountThread parallelly, then yes, you would have synchronization problem.
To verify that, you can try to print some test output before count++ and after, then you'll see if b.start() is invoking count++ before a.start() finished. Same for c.start().
Consider using AtomicInteger instead, which is way better than synchronizing when possible -
incrementAndGet
public final int incrementAndGet()
Atomically increments by one the current value.
This code is not thread-safe:
public static int count = 0;
class CountThread extends Thread {
public void run()
{
count++;
}
}
You can run this code a million times on one system and it might pass every time. This does not mean is it is thread-safe.
Consider a system where the value in count is copied to multiple processor caches. They all might be updated independently before something forces one of the caches to be copied back to main RAM. Consider that ++ is not an atomic operation. The order of reading and writing of count may cause data to be lost.
The correct way to implement this code (using Java 5 and above):
public static java.util.concurrent.atomic.AtomicInteger count =
new java.util.concurrent.atomic.AtomicInteger();
class CountThread extends Thread {
public void run()
{
count.incrementAndGet();
}
}
It's not thread safe just because the output is right. Creating a thread causes a lot of overhead on the OS side of things, and after that it's just to be expected that that single line of code will be done within a single timeslice. It's not thread safe by any means, just not enough potential conflicts to actually trigger one.
It is not thread safe.
It just happened to be way to short to have measurable chance to show the issue. Consider counting to much higher number (1000000?) in run to increase chance of 2 operations on multiple threads to overlap.
Also make sure your machine is not single core CPU...
To make the class threadsafe either make count volatile to force memory fences between threads, or use AtomicInteger, or rewrite like this (my preference):
class CountThread extends Thread {
private static final Object lock = new Object();
public void run()
{
synchronized(lock) {
count++;
}
}
}

What is the difference between synchronized and static synchronized?

For a travel booking web application, where there are 100 concurrent users logged in,
should ticket booking and generating an "E-Ticket Number" be implemented by a "synchronized" or a "static synchronized" method?
Well, are you aware of the difference between a static method and an instance method in general?
The only difference that synchronized makes is that before the VM starts running that method, it has to acquire a monitor. For an instance method, the lock acquired is the one associated with the object you're calling the method on. For a static method, the lock acquired is associated with the type itself - so no other threads will be able to call any other synchronized static methods at the same time.
In other words, this:
class Test
{
static synchronized void Foo() { ... }
synchronized void Bar() { ... }
}
is roughly equivalent to:
class Test
{
static void Foo()
{
synchronized(Test.class)
{
...
}
}
void Bar()
{
synchronized(this)
{
...
}
}
}
Generally I tend not to use synchronized methods at all - I prefer to explicitly synchronize on a private lock reference:
private final Object lock = new Object();
...
void Bar()
{
synchronized(lock)
{
...
}
}
You haven't provided nearly enough information to determine whether your method should be a static or instance method, or whether it should be synchronized at all. Multithreading is a complex issue - I strongly suggest that you read up on it (through books, tutorials etc).
Jon's answer covers the difference hinted at in your question title.
However, I would say that neither should be used for generating a ticket number. On the assumption that these are being stored in a database, somewhere - the database should be responsible for generating the number when you insert the new record (presumably by an autoincrementing primary key, or something similar).
Failing that, if you must generate the number within Java code, I suspect that the synchronisation overhead might be quite noticeable with 100 concurrent users. If you are running on Java 1.5 or later, I'd use a java.util.concurrent.AtomicInteger to get the ticket number, which you can simply call as
private static final AtomicInteger ticketSequence;
static
{
final int greatestTicket = getHighestExistingTicketNumber(); // May not be needed if you can start from zero each time
ticketSequence = new AtomicInteger(greatestTicket + 1);
}
public /*static*/ int getNextTicketNumber()
{
return ticketSequence.incrementAndGet();
}
This gives you the concurrent global uniqueness you need in a much more efficient fashion than synchronizing every time you need an integer.

Categories

Resources