Is this thread-safe ? (Part 1)
To learn and understand about thread-safety or concurrency in general, there can’t be a better book than “Java Concurrency in Practice”
Even if you cannot find the time to read through the book, the booksite contains a lot of code snippets on thread-safe / non-thread-safe code, which I’d highly recommend going through.
In this blog post, I have added a few classes, some of them are thread-safe and some of them are not. Take it up as a quick quiz or an exercise to identify which are thread-safe and which are not and see how well you fair 🙂
public class One { public void aMethod() { int a = 100; a++; System.out.println(a); } }
There’s no “mutable-shared-state” in the above class. So yeah, it is thread-safe.
class Two { private int a = 100; public void aMethod() { a++; System.out.println(a); } }
In class Two, ‘a’ is a mutable shared state and the operation being done (a++) is not atomic. This could lead to race-conditions
and hence class Two is not thread-safe
class Three { private boolean toggleSwitch = true; public void aMethod() { toggleSwitch = !toggleSwitch; System.out.println(toggleSwitch); } }
When two threads are changing the state (toggleSwitch) you cannot guarantee that the change done by threadA is visible for the
other thread. So we have got ‘thread-visibility’ problems in the above class.
class Four { private volatile boolean toggleSwitch = true; public void aMethod() { toggleSwitch = !toggleSwitch; System.out.println(toggleSwitch); } }
We’ve addressed the problem we had at ‘class Three’ by making ‘toggleSwitch’ volatile. So we are good for class Four. Class Four is thread-safe. Update: Oops, wait ! Class Four is not thread safe. As Pravin has pointed out in the comments-
class Five { private volatile int a = 100; public void aMethod() { a++; System.out.println(a); } }
This code looks pretty much like class Four. So is this thread-safe too ? Nope.
Visibility and atomicity are two separate things. Here a++ is not an atomic operation and you could have a race condition. So class Five is not thread safe.
class Six { private AtomicInteger a = new AtomicInteger(100); public void aMethod() { a.incrementAndGet(); System.out.println(a); } }
We’ve addressed the atomicity problem. Atomic* operations are also documented to behave like ‘volatile’. So visibility is covered too
so class Six here is thread-safe.
class Seven { int a = 100; public synchronized void aMethod() { a++; System.out.println(a); } }
Note that ‘a’ is not private. Nothing prevents a thread from directly accessing the field and modifying the state. So class Seven is not thread-safe
class Eight{ private int a = 100; public synchronized void aMethod() { a++; System.out.println(a); } }
Well, only aMethod() could change the state of ‘a’ now. And it is synchronized.
So yeah, class Eight is thread-safe. But we did not make ‘a’ volatile !
Well, there’s no need to. ‘Synchronizing’ addresses both ‘atomicity’ and ‘thread visibility’ problems so we are good here.
Resources:
Apart from the book, do check out the “concurrency animations” !
In class 4, don’t you think that “toggleSwitch = !toggleSwitch;” is not atomic?
Pravin
June 13, 2014 at 3:45 pm
Yes, you’re right. That is not atomic and hence not thread-safe. Thanks for pointing it out ! For mere ‘read’s or ‘write’s a volatile boolean would have sufficed but for a ‘read-modify-write’ operation, as it was in this case, there’s atomicity to consider as well.
Vishwanath Krishnamurthi
June 22, 2014 at 10:39 am
Good post, Vishwanath. JCP is a must read for any serious java developer.
Shridhar
August 9, 2016 at 2:02 am
[…] at this blog, Vishwanath tells us something interesting. Never stake entirely on such a code to give you […]
Thread visibility issues during concurrency – learn coding or die trying
June 12, 2020 at 7:13 pm