I was going through an "JAX London 2011" presentation on "Modern Java Concurrency". Between the time duration 43:20 - 43:40, a person from the audience says the shutdown variable in the code below should have been declared as volatile and the presenters agree with it (and say that it was pointed out earlier as well, but they just didnt get to modify the presentation). The code in question is:
public abstract class QueueReaderTask implements Runnable {
private boolean shutdown = false;
protected BlockingQueue<WorkUnit<String>> lbq;
public void run() {
while (!shutdown) {
try {
WorkUnit<String> wu = lbq.poll(10, TimeUnit.MILLISECONDS);
if (wu != null) { doAction(wu.getWork()); }
} catch (InterruptedException e) {
shutdown = true;
}
}
}
public abstract void doAction(String msg);
public void setQueue(BlockingQueue<WorkUnit<String>> q) { lbq = q; }
}
My Question:
I dont think that shutdown should be declared volatile.
My reasoning is that shutdown being a member of a Runnable, each task/thread will have a distinct private copy of that variable. So, why make it volatile?
But since this was discussed in JAX 2011, I am assuming there were lots of expert Java developers in that audience. I dont think all of them would have missed this !
So, what am I missing ?
P.S:-
I can understand that a variable should be declared volatile if it was (potentially) shared by multiple threads, as in the Double-Checked-Locking pattern :
class Foo {
private volatile Helper helper = null;
public Helper getHelper() {
if (helper == null) {
synchronized(this) {
if (helper == null)
helper = new Helper();
}
}
return helper;
}
}
each task/thread will have a distinct private copy of that variable. So, why make it 'volatile' ?
You are correct if the shutdown boolean is only modified from within the QueueReaderTask instance. In that case shutdown is only being modified by the one thread and doesn't need to be volatile.
Frankly, the code looks strange to me. Why catch InterruptedException, set the shutdown boolean, and then loop around and exit. Why now just do the following? Why have the shutdown flag at all?
while (true) {
try {
WorkUnit<String> wu = lbq.poll(10, TimeUnit.MILLISECONDS);
if (wu != null) { doAction(wu.getWork()); }
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return;
}
}
Maybe there is extra code that was removed in the post? If not, I wonder if this was copy and pasted from a larger section of code where shutdown was set to true also in a method call.
P.S:- I can understand that a variable should be declared 'volatile' if it was (potentially) shared by multiple threads, as in the Double-Checked-Locking pattern :
Right. A typical pattern is that shutdown is modified from another thread which is telling the thread to stop processing. In that case it needs to be volatile.
Related
I have the following two methods in a class:
private MyDef myDef;
private FutureTask<MyDef> defFutureTask;
public synchronized void periodEviction() {
myDef = null;
}
public MyDef loadMyItems() {
// if it's not ready use a future - it will block until the results are ready
if (this.myDef == null) { // this will still not be thread safe
Callable<MyDef> callableDef = ()->{ return this.loadFromDatabase(); };
FutureTask<MyDef> defTask = new FutureTask<>(callableDef);
this.defFutureTask = defTask;
defFutureTask.run();
}
try {
// wait until's it's ready
this.myDef = this.qDefFuture.get();
} catch(InterruptedException e) {
log.error(this.getClass(), "Interrupted whilst getting future..");
} catch(ExecutionException e) {
log.error(this.getClass(), "Error when executing callable future");
}
return this.myDef;
}
I wanted to do the following:
1) Do a cache eviction using periodEviction() every one hour or so.
2) Otherwise, use the cached value when db loading is done.
I believe I have misunderstood Java future as I couldn't answer the question, "What happens when Thread A,B,and C all are calling loadMyItems() at the same time?"
So does this mean without something like an executor, this implementation is still not thread safe?
An even simpler approach is to not cache the object at all but just retain the Future.
private CompletableFuture<MyDef> defFuture;
public synchronized void periodEviction() {
// evict by triggering the request anew
defFuture = CompletableFuture.supplyAsync(this::loadFromDatabase);
}
public synchronized Optional<MyDef> loadMyItems() {
try {
return Optional.of(this.defFuture.get());
} catch(InterruptedException e) {
log.error(this.getClass(), "Interrupted whilst getting future..");
} catch(ExecutionException e) {
log.error(this.getClass(), "Error when executing callable future");
}
return Optional.empty();
}
With the caveat that this will trigger the database query every eviction period rather than on demand.
A super simple approach would be to declare loadMyItems as synchronized. But if the class has other methods that access myDef, you would have to declare those synchronized too. Sometimes this results in very coarse-grained locking and slower performance.
If you're looking for the cleanest/fastest code, instead of declaring periodEviction as synchronized, declare myDef as an AtomicReference:
private final AtomicReference<MyDef> myDef = new AtomicReference<>();
Then the body of periodEviction is:
synchronized (myDef) {
myDef.set(null);
}
And the body of loadMyItems is:
synchronized (myDef) {
if (myDef.get() == null) {
// perform initialization steps, ending with:
myDef.set(this.qDefFuture.get());
}
return myDef.get();
}
If many threads call loadMyItems at the same time, myDef will only ever be initialized once, and they will all get the same object returned (unless somehow a call to periodEviction snuck in the middle).
Is there a way to fail-fast as soon as multiple threads enter a method which is known not to be thread-safe?
Edit: Assuming a method is synchronized externally and not supposed to run concurrently. However, if external synchronization fails for some reason, it would be great to fail as soon as possible, thus avoiding subtle race-condition issues. Also, since the method normally runs in a single thread only, would be great to avoid/minimize synchronization penalty of the check.
The lock solutions, here, all add performance overhead, and I'm guessing you didn't make the class thread-safe for that reason. Java's collections are in the same situation, and they solved it with a "mod count" field in the class. It's not perfect (AtomicInteger would be better), and it's not guaranteed, but it catches most cases.
public class Foo {
private volatile int modCount = 0;
public void threadUnsafeMethod() {
int startModCount = ++modCount;
...
if (modCount != startModCount) { throw new ConcurrentModificationException(); }
}
}
If you just want to guard, you could do
public class Foo {
private final AtomicBoolean inThreadUnsafeMethod = new AtomicBoolean();
public void threadUnsafeMethod() {
if (!inThreadUnsafeMethod.compareAndSet(false, true) {
throw new ConcurrentModificationException();
}
try {
...
} finally {
inThreadUnsafeMethod.set(false);
}
}
}
With both, be very careful with handle reentrant calls correctly. this.otherThreadUnsafeMethod(); shouldn't fail.
Take a look at the ArrayList implementation (search for modCount).
I use an AtomicBoolean. First we have:
private final AtomicBoolean isExecuting = new AtomicBoolean();
Then, first thing we do in method not supposed to be executed concurrently:
if (isExecuting.getAndSet(true)) {
throw new UnsupportedOperationException();
}
Make sure that the one thread executing your method reset the flag on exit:
try {
// ... method implementation
}
finally {
isExecuting.set(false);
}
You may see two real world examples here and here.
You could create a lock and a wrapper method and then you can make each caller to invoke this method
private final Lock lock = new ReentrantLock();
public void wrapperMethod() {
if (!lock.tryLock())
throw new RuntimeException()
try {
threadUnsafeMethod();
}
finally {
lock.unlock();
}
}
With tryLock the caller tries to acquire the lock immediately. If the lock is already been acquired by some other caller it returns false and we throw an exception.
If you want to make each caller to fail fast in case of concurrent invocations, then it means that no two threads access the method concurrently. Otherwise, one of the two threads must have failed. This way you effectively add thread safety to your method.
An equivalent method using atomic longs but that remains a locking mechanism:
AtomicLong threadId = new AtomicLong(-1);
public void wrapperMethod() {
threadId.compareAndSet(-1, Thread.currentThread().getId());
if (threadId.get() != Thread.currentThread().getId())
throw new RuntimeException();
try {
threadUnsafeMethod();
}
finally {
threadId.set(-1);
}
}
Saying that, if you allow to use only a specific thread to run the code, this gives the idea for threads to run a contest. Then use only the winner for running the method:
AtomicLong winningThreadId = new AtomicLong(-1);
public void runContest() {
winningThreadId.compareAndSet(-1, Thread.currentThread().getId());
}
public void wrapperMethod() {
if (winningThreadId.get() != Thread.currentThread().getId())
throw new RuntimeException();
threadUnsafeMethod();
}
So every candidate thread runs the contest once and afterwards it uses the wrapper method.
I'm just testing some concurrent programming in Java.
Basically I have a class (Light) which is a kind of finite state machine, and changing its state regarding the commands.
That's what I'm trying to: The light is in ON state, I send a command to the thread of this class for changing the state in OFF.
But I got a problem during the execution.
First, let me present the class:
enum State {ON, OFF};
public class Light implements Runnable {
private boolean cmdOn;
private boolean cmdOff;
State state;
public Light() {
cmdOn = false;
cmdOff = false;
state = State.ON;
}
#Override
public void run() {
while(true) {
switch(state) {
case ON:
if(cmdOff) {
try {
Thread.currentThread().sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
state = State.OFF;
}
break;
case OFF:
if(cmdOn) {
try {
Thread.currentThread().sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
state = State.ON;
}
break;
}
}
}
public void setCmdOn(boolean cmdOn) {
this.cmdOn = cmdOn;
}
public void setCmdOff(boolean cmdOff) {
this.cmdOff = cmdOff;
}
public State getState() {
return state;
}
}
And my main class:
public class Main {
public static void main(String args[]) throws InterruptedException {
Light light = new Light();
Thread t = new Thread(light);
t.start();
printState(light, 500, 1);
light.setCmdOff(true);
printState(light, 500, 4);
}
public static void printState(Light l, int time, int number) throws InterruptedException {
for(int i= 0; i < number; i++) {
System.out.println(l.getState());
Thread.currentThread().sleep(time);
}
}
The output shows me that I'm stuck in the ON state while I should be in OFF state.
In a second run, after putting an instruction (System.out.println or whatever...) above the if statement which verify that cmdOff is true, it's magically works.
I don't understand why the cmdOff variable is not pass to true during the first run !?
And why in the second run it works?
I miss something, probably a synchronizing block. But I don't find the explanation to deal with this.
Thanks.
Best regards,
You should read about synchronization. Without synchronization you risk getting visibility errors where one thread can't see changes another thread made to a variable shared between the threads.
Tutorial: http://docs.oracle.com/javase/tutorial/essential/concurrency/sync.html
You can use a synchronized block that uses an object both threads know about to do locking. If both threads always synchronize on that known object when reading or updating your shared data, then visibility and atomicity will never be an issue.
Read here to fully understand "synchronized": http://tutorials.jenkov.com/java-concurrency/synchronized.html
You should also be able to just declare the shared variable as volatile. This means all writes and reads on it create a happens-before relationship with other threads, which is what you want. Read the tutorial above to fully understand the issues and terminology.
Read here to fully understand "volatile": http://docs.oracle.com/javase/tutorial/essential/concurrency/atomic.html.
Try using volatile on cmdOn and cmdOff:
private volatile boolean cmdOn;
private volatile boolean cmdOff;
Volatile variable explanation in Java docs
Without it (or synchronization) changes may not be visible.
Without any synchronization, there are no guarantees that the running thread will ever see the values written to cmdOff and cmdOn by the other thread. Also, lack of synchronization on state means any changes by the running thread may not be seen by the other thread. Try making cmdOn, cmdOff and state volatile .
I have this method which takes a thread as a parameter. I want this method to be able to make a thread wait if there is not one waiting already and then wake up when another thread comes into the method so that the two of them can interact. I think I'm close but after I call wait() on the first thread no other threads can gain access to that method. Here is a minimalist version of my code:
// In the class 'Node'
public synchronized void trade(Thread thread)
{
if (!threadWaiting)
{
threadWaiting = true;
synchronized(thread)
{
try {
thread.wait();
} catch (InterruptedException e) {...}
}
}
}
I apologise for missing anything obvious, I've been looking around for an answer but I'm new to threading so I've no idea what to look for.
So my problem is that when another thread attempts to get into trade() they can't, the debugger just stops right there.
EDIT:
Here's some more clarification on what I'm asking. I'm afraid I wasn't too clear in my original post.
So I have one class called Node and another class called Bot. Bot extends thread so that it can be paused. At the start of the program multiple Bot objects are created and are then started, each Bot will then call the trade() method of the Node and pass itself to the method. If a Bot is the first in the method then I want its thread to wait on the Node until another Bot comes along (The waiting Bot will be stored in the Node), at which point the two Bots will interact.
Below is a clearer example of my method in pseudo code:
// Variable to hold the bot that is waiting.
private Bot waitingBot = null;
// Method belonging to Node.
public synchronized void trade(Bot currentBot)
{
if (waitingBot == null)
{
waitingBot = currentBot;
waitingBot.wait();
}
else
{
currentBot.interactWith(waitingBot);
waitingBot.notify();
waitingBot = null;
}
}
Sorry about the wording of my original post.
Your implementation has a flaw. You are taking lock on parameter passed which will be different for all Threads so they can't interact with wait notify.
EDIT: I am not sure what exactly your aim is but based on details this might help:
EDIT2: Added lock()
private final Lock lck = new ReentrantLock();
private final Condition cnd = lck.newCondition();
private final AtomicBoolean threadwaiting = new AtomicBoolean(false);
public synchronized void trade(Thread thread)
{
lck.lock();
try{
if(threadwaiting.get()){
cnd.signalAll();
threadwaiting.set(false);
//perform your task
}else{
cnd.await();
threadwaiting.set(true);
}
}
} finally {
lck.unlock()
}
}
EDIT:
Looking at your updated post , you should use cyclicbarrier with count 2 then that should solve it all for you.
This is a dead lock, because when you call thread.wait(); you release thread object lock. But this object lock on synchronized method remains, that's why no one else can enter it.
It's like loki's code, but improved
private final Lock lock = new ReentrantLock();
private final Condition cnd = lock.newCondition();
private final AtomicBoolean threadwaiting = new AtomicBoolean(false);
public void trade(Thread thread) {
lock.lock();
if (threadwaiting.get()) {
cnd.signalAll();
lock.unlock();
// perform your task of second thread
} else {
threadwaiting.set(true);
try {
cnd.await();
// perform your task of first thread
} catch (InterruptedException e) {
} finally {
threadwaiting.set(false);
lock.unlock();
}
}
}
I have a method, say method1(), that takes a while to run. During it's execution, if there is another call to method1(), it should be ignored. I have, roughly, something like this
boolean mFlag = false;
void method1()
{
if(!mFlag)
{
mFlag=true;
// do Stuff
mFlag=false;
}
}
This works. But I was wondering if there is a better way to do this preferably not involving any flags.
Yes, you should really be using something from java.util.concurrent.locks Your example isn't quite strictly correct, that boolean needs to be volatile.
ReentrantLock lock = new ReentrantLock();
void method1()
{
if(lock.tryLock())
{
try {
if (!(lock.getHoldCount() > 1)) {
//do Some Stuff
}
} finally {
lock.unlock();
}
}
}
Edited to handle skipping execution on reentrance as inidicated in your comment. Unfortunatly there isn't really a great way to do that with the built in library, as it's a bit of an odd usecase, but I still think using the built in library is a better option.
Are you trying to guard against re-entry from the same thread or multiple threads accessing at the same time.
Assuming multi-threaded access, the light approach is to use java.util.concurrent.atomic. No need for anything as "heavy" as a lock (provided there are not further requirements).
Assuming no-reentry from the same method:
private final AtomicBoolean inMethod = new AtomicBoolean();
void method1() {
if (inMethod.compareAndSet(true, false)) { // Alternatively getAndSet
try {
// do Stuff
} finally {
inMethod.set(false); // Need to cover exception case!
}
}
}
If you want to allow reentry within the same thread, then it gets messy enough to use locks:
private final AtomicReference<Thread> inMethod = new AtomicReference<Thread>();
void method1() {
final Thread current = Thread.currentThread();
final Thread old = inMethod.get();
if (
old == current || // We already have it.
inMethod.compareAndSet(null, current) // Acquired it.
) {
try {
// do Stuff
} finally {
inMethod.set(old); // Could optimise for no change.
}
}
}
Could use the Execute Around idiom for this.
Maybe you should use synchronized methods
http://download.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html