AtomicBoolean vs Synchronized block, whats the difference - java

I am trying to understand the difference between the two following code blocks
AtomicBoolean ab = new AtomicBoolean(false);
using the following to get and set state. .
ab.get();
ab.set(X);
vs.
private boolean ab = false;
private final Object myboollock = new Ojbect();
public void setAB(boolean state)
{
synchronized(myboollock)
{
ab = state;
}
}
public boolean getAB()
{
synchronized(myboollock)
{
return ab;
}
}
I need to thread protect a boolean, that is all, and have
in the past used the later method, but would like to start to use Atomic
objects, (if ) they are safe?,

If all you're trying to do is make getting and setting a single boolean value atomic, then yes - you can use AtomicBoolean instead without any synchronization.
Of course, synchronized allows a far wider range of uses, such as performing several actions within the block without losing the lock, or using it for wait/notify. So it's not like AtomicBoolean is a general alternative to synchronization - but in this case you can use it instead of synchronization.

There are a few subtle differences but seen from the outside the two code snippets behave similarly: if you call the set method, the change will be visible to other threads calling get subsequently.
The main differences are:
performance: depending on the level of contention, you may get better performance with synchronized or AtomicBoolean
atomicity: if at some stage you want to do more than just setting the boolean value, a synchronized block will allow you to add instructions atomically but AtomicBoolean won't

Related

Using a boolean to coordinate two threads in Java

I understand the code section below is problematic because the new value of isAlive set in the kill method might not be visible in the thread.
public class MyClass extends Thread {
private boolean isAlive;
public void run() {
while(isAlive) {
....
}
}
public void kill() {
isAlive = false;
}
}
The typical fix is to declare the isAlive variable as volatile.
My question here is that is there any other ways to achieve this without using volatile? Does Java provide other mechanisms to achieve this?
EDIT: Synchronize the method is also not an option.
There is no good reason to go for a different option than volatile. Volatile is needed to provide the appropriate happens-before edge between writing and reading; otherwise you have a data-race on your hands and as a consequence the write to the flag might never be seen. E.g. the compiler could hoist the read of the variable out of a loop.
There are cheaper alternative that provide more relaxed ordering guarantees compared to the sequential consistency that volatile provides. E.g. acquire/release or opaque (check out the Atomic classes and the VarHandle). But this should only be used in very rare situations where the ordering constraints reduce performance due to limited compiler optimizations and fences on a hardware level.
Long story short: make the variable volatile because it a simple and very fast solution.
There are three options:
Make the shared variable volatile. (This is the simplest way.)
Use synchronized, either in the form of synchronized methods or synchronized blocks. Note that you need to do both reads and writes for the shared variables while holding the (same) mutex.
Use one of the classes in java.util.concurrent that has a "synchronizing effect"1. Or more precisely, one that you can use to get a happens before relationship between the update and subsequent read of the isAlive variable. This will be documented in the respective classes javadocs.
If you don't use one of those options, it is not guaranteed2 that the thread that calls run() will see isAlive variable change from true to false.
If you want to understand the deep technical reasons why this is so, read Chapter 17.4 of the Java Language Specification where it specifies the Java Memory Model. (It will explain what happens before means in this context.)
1 - One of the Lock classes would be an obvious choice.
2 - That is to say ... your code may not work 100% reliably on all platforms. This is the kind of problem where "try it and see" or even extensive testing cannot show conclusively that your code is correct.
The wait/notify mechanism is embedded deep in the heart of the java language, the superclass of classes, has five methods that are the core of the wait/notify mechanism, notify(), notifyAll(), wait(), wait(long), and wait(long, int), all classes in java inherit from Object, in addition, none of these methods can be overridden in a subclass as they are all declared final
here is an example that may help you to understand the concept
public class NotifyAndWait {
public List list;
public NofityAndWait() { list = Collections.synchronizedList(new LinkedList ());
public String removeItem() throws InterruptedException {
synchronized(list) {
while(list.isEmpty())
list.wait();
}
String item = list.remove(0);
return item;
}
public void addItem(String item) {
synchronized(list) {
list.add(item);
//after adding, nofity and waiting all thread that the list has changed
list.notifyAll();
}
}
public static void main(String..args) throws Exception {
final NotifyAndWait obj = new NotifyAndWait();
Runnable runA = new Runnable() {
public void run() {
try {
String item = enf.removeItem();
catch(Exception e) {} };
Runnable runB = new Runnable() {
public void run() { obj.addItem("Hello"); }
};
Thread t1 = new Thread(runA, "T1");
t1.start();
Thread.sleep(500);
Thread t2 = new Thread(runB, "T2");
t2.start();
Thread.sleep(1000);
}
}
As far as I know, polling a boolean in a while loop as a "kill" control is a perfectly reasonable thing to do. Brian Goetz, in "Java Concurrency in Action" has a code example that is very similar to yours, on page 137 (section 7.1 Task Cancellation).
He states that making the boolean volatile gives the pattern greater reliability. He has a good description of the mechanism on page 38.
When a field is declared volatile, the compile and runtime are put on
notice that this variable is shared and that operations on it should
not be reordered with other memory operations. Volatile variables are
not cached in registers or in caches where they are hidden from other
processors, so a read of a volatile variable always returns the most
recent write by any thread.
I use volatile booleans and loose coupling as my main method of communication that must occur across threads. AFAIK, volatile has a smaller cost than synchronized and is the most recommended pattern for this situation.

Atomically update multiple volatile and j.u.c.atomic variables

In order to atomically update two and more volatile variables does it need to be guarded by lock with synchronized, reentrantReadWriteLock etc?
i.e.
volatile int vVar1, vVar1; // or AtomicInteger
/*** Needs to be updated atomically ***/
void atomicUpdate(int var1, int var2){
vVar1 = var1;
vVar2 = var2;
}
The same code is for java.util.concurrent.atomic variables.
If you need to assign two values atomically, chaning volatile int to AtomicInteger will not solve your race condition problem.
To solve your issue, you basically have two options:
Make the methods updating the variables synchronized (and maybe the methods reading those variables too)
Create an wrapper for your two variables, and make use of the fact that assignment is an atomic operation
Example for option 2:
volatile Vars vars;
void atomicUpdate(int var1, int var2) {
vars = new Vars(var1, var2);
}
public static Vars {
private int vVar1; // volatile if they need to be modified
private int vVar2;
}
I largely prefer option 2 since it is non blocking and allows you to cache any type of data.
Create a Class which encapsulates all of your state variables, then use AtomicReference to refer to them. This alleviates race conditions where a thread needs to set/check multiple values safely.
// set initial state
AtomicReference<MyState> ref = new AtomicReference<MyState>();
ref.set(new MyState("abc", "def"));
// .. Thread 1 needs to change the state:
ref.set(new MyState("xyz", "def"));
// .. Thread 2 needs to read the state (consistently):
MyState state = ref.get();
if ("test1".equals(state.a)) { }
else if ("test2".equals(state.b) { }
The benefit here is that Thread 2 is able to read MyState.a and MyState.b consistently from the same MyState instance, as opposed to having the MyState instance variable it's referencing change in-between checks.
I want to update my two variables atomically
You can't. There are no atomic operations in the Java language or in the Java standard library that span more than one variable.
You can probably solve your problem using the synchronized keyword, but using synchronized is different from using atomics because, in order for it to work, the threads must cooperate with one another.
If there is a specific relationship that must always exist between those two variables (a.k.a., an invariant), and if you can't update the variables without temporarily breaking the invariant, then you must synchronize the code that does the update, and you must also synchronize every other block of code that expects the invariant to be true.
That's because, when you write this:
synchronized(foo) { ... }
It doesn't prevent other threads from doing anything except synchronizing on the same object at the same time.
Also note: Once you have properly synchronized all access to the variables, then you won't need them to be volatile. That's because whatever one thread writes to memory before releasing a lock is guaranteed to become visible to any other thread that subsequently acquires the same lock.
An alternative would be to use a volatile array:
private volatile int[] var;
void update (int var1, int var2) {
var = new int[] { var1, var2 };
}
that would be atomic but it assumes that the rest of your code does not access vVar1 and vVar2 directly. There may be better options depending on what you are trying to achieve - for example you could create an ad hoc thread safe holder class (typically immutable) for the two ints.

Is AtomicBoolean needed to create a cancellable thread?

I often use the following pattern to create a cancellable thread:
public class CounterLoop implements Runnable {
private volatile AtomicBoolean cancelPending = new AtomicBoolean(false);
#Override
public void run() {
while (!cancelPending.get()) {
//count
}
}
public void cancel() {
cancelPending.set(true);
}
}
But I'm not sure that cancelPending MUST be a AtomicBoolean. Can we just use a normal boolean in this case?
Using both volatile and AtomicBoolean is unnecessary. If you declare the cancelPending variable as final as follows:
private final AtomicBoolean cancelPending = new AtomicBoolean(false);
the JLS semantics for final fields mean that synchronization (or volatile) will not be needed. All threads will see the correct value for the cancelPending reference. JLS 17.5 states:
"An object is considered to be completely initialized when its constructor finishes. A thread that can only see a reference to an object after that object has been completely initialized is guaranteed to see the correctly initialized values for that object's final fields."
... but there are no such guarantees for normal fields; i.e. not final and not volatile.
You could also just declare cancelPending as a volatile boolean ... since you don't appear to be using the test-and-set capability of AtomicBoolean.
However, if you used a non-volatile boolean you would need to use synchronized to ensure that all threads see an up-to-date copy of the cancelPending flag.
You can use a volatile boolean instead with no issues.
Note that this only applies in cases much like this where the boolean is only being changed to a specific value (true in this case). If the boolean might be changed to either true or false at any time then you may need an AtomicBoolean to detect and act on race conditions.
However - the pattern you describe has an innate smell. By looping on a boolean (volatile or not) you are likely to find yourself trying to insert some sort of sleep mechanism or having to interrupt your thread.
A much cleaner route is to split up the process into finer steps. I recently posted an answer here covering the options of pausing threads that may be of interest.
No, you can not. Because if you will change the boolean value from another thread without proper synchronization then this change can be invisible to another threads. You can use valotile boolean in your case to make any modification visible to all threads.
Yes you can. You can either use a non volatile AtomicBoolean (relying on its built in thread safety), or use any other volatile variable.
According to the Java Memory Model (JMM), both options result in a properly synchronized program, where the read and write of the cancelPending variable can't produce a data race.
Using a volatile boolean variable in this context is safe, though some may consider it bad practice. Consult this thread to see why.
Your solution of using an Atomic* variable seems the best option, even though the synchronization may introduce unnecessary overhead in comparison to a volatile variable.
You can also use a critical section
Object lock = new Object();
#Override
public void run() {
synchronized (lock) {
if (cancelPending) {
return;
}
}
}
or a synchronized method.
synchronized public boolean shouldStop() {
return shouldStop;
}
synchronized public void setStop(boolean stop) {
shouldStop = stop;
}

It's acceptable to always use 'this' as monitor lock?

For example I have a class with 2 counters (in multi-threaded environment):
public class MyClass {
private int counter1;
private int counter2;
public synchronized void increment1() {
counter1++;
}
public synchronized void increment2() {
counter2++;
}
}
Theres 2 increment operations not related with each other. But I use same object for lock (this).
It is true that if clients simultaneously calls increment1() and increment2() methods, then increment2 invocation will be blocked until increment1() releases the this monitor?
If it's true, does it mean that I need to provide different monitor locks for each operation (for performance reasons)?
It is true that if clients simultaneously calls increment1() and increment2() methods, then increment2 invocation will be blocked until increment1() releases the this monitor?
If they're called on the same instance, then yes.
If it's true, does it mean that I need to provide different monitor locks for each operation (for performance reasons)?
Only you can know that. We don't know your performance requirements. Is this actually a problem in your real code? Are your real operations long-lasting? Do they occur very frequently? Have you performed any diagnostics to estimate the impact of this? Have you profiled your application to find out how much time is being spent waiting for the monitor at all, let alone when it's unnecessary?
I would actually suggest not synchronizing on this for entirely different reasons. It's already hard enough to reason about threading when you do control everything - but when you don't know everything which can acquire a monitor, you're on a hiding to nothing. When you synchronize on this, it means that any other code which has a reference to your object can also synchronize on the same monitor. For example, a client could use:
synchronized (myClass) {
// Do something entirely different
}
This can lead to deadlocks, performance issues, all kinds of things.
If you use a private final field in your class instead, with an object created just to be a monitor, then you know that the only code acquiring that monitor will be your code.
1) yes it's true that increment1() blocks increment2() and vice versa because they both are implicitly synchronizing on this
2) if you need a better performance consider the lock-free java.util.concurrent.atomic.AtomicInteger class
private AtomicInteger counter1 = new AtomicInteger();
private AtomicInteger counter2 = new AtomicInteger();
public void increment1() {
counter1.getAndIncrement();
}
public void increment2() {
counter2.getAndIncrement();
}
If you synchonize on the method, as what you did here, you lock the whole object, so two thread accessing a different variable from this same object would block each other anyway.
If you want to syncrhonize only a counter at a time so two thread won't block each other while accessing different variables, you have to add the two counters here in two synchronized block, and use different variables as the "lock" of the two blocks.
You are right it will be a performance bottleneck if you use same Object. You can use different lock for individual counter or use java.util.concurrent.atomic.AtomicInteger for concurrent counter.
Like:
public class Counter {
private AtomicInteger count = new AtomicInteger(0);
public void incrementCount() {
count.incrementAndGet();
}
public int getCount() {
return count.get();
}
}
Yes the given code is identical to the following:
public void increment1() {
synchronized(this) {
counter1++;
}
}
public oid increment2() {
synchronized(this) {
counter2++;
}
}
which means that only one method can be executed at the same time. You should either provide different locks (and locking on this is a bad idea to begin with), or some other solution. The second one is the one you actually want here: AtomicInteger
Yes if multiple threads try to call methods on your object they will wait trying to get the lock (although the order of who gets the lock isn't guaranteed.) As with everything there is no reason to optimise until you know this is the bottle neck in you code.
If you need the performance benefits that can be had from being able to call both operations in parallel, then yes, you do not to provide different monitor objects for the different operations.
However, there is something to be said for premature optimization and that you should make sure that you need it before making your program more complex to accommodate it.

Java: What is the different between AtomicBoolean and a static boolean variable when locking a thread?

I write a thread class called T.
My purpose is to make sure only one thread object running at a time.
So when the thread object is called, it would check a boolean flag called BUSY.
My question is what is the different between
private static AtomicBoolean BUSY = new AtomicBoolean(false);
and
private static boolean BUSY = false;
I thought if using the 'static', all object would only check one BUSY boolean variable so that would make sure only one thread object is running.
You must at least make the boolean variable volatile and the AtomicBoolean variable final in order to have a comparable solution. After you do that, there will be no difference for your use case.
The difference comes about if you use AtomicBoolean's getAndSet or compareAndSet methods, which combine one read and one write action into an atomic whole, wheraas these are not atomic when done against a volatile.
You can use a boolean and with proper synchronization (and making volatile) can achieve what you need.
But by using the AtomicBoolean you can check the current value atomically without the need to write code for synchronization yourself
As said by others you must make the variables final / volatile respectively.
From what you describe I fear you have a place where you do something like this:
if (!BUSY){
BUSY = true;
}
Note that this is broken in absence of commons synchronization, because two threads might check the flag, both seeing it as false and starting their work.
I suggest looking into the existing structures for handling concurrency: http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/package-summary.html
Especially Semaphore with a single permit might be what you are looking for.
A useful feature of an AtomicBoolean is to allow a single thread to continue if and only if BUSY is false but not to let any other threads to continue.
private static AtomicBoolean BUSY = new AtomicBoolean(false);
public void doWork(){
if(BUSY.compareAndSet(false,true)){
//do some work
BUSY.set(false);
}else{
//some other thread won, return now or retry later?
}
}
So here only one thread will doWork at any given time. You cannot achieve this with a volatile boolean because you cannot be sure that Thread.currentThread() set the boolean.

Categories

Resources