I've read about the 'status flag' pattern for the volatile usage.
It says that I can use the volatile without any sync if the status flag doesn't depend on any other state. It will guarantee the visibility of the flag for other threads. Moreover, write to the boolean is atomic.
But in the other related question it's said that it's safe to use the volotile when only one thread can modify the flag. Otherwise, I need to use any synchronization or AtomicBoolean.
In my example, I have the stopped flag, but it could be modified more than from within one thread: methods stop() and continue(). The doSmth() doesn't update any states. If assume that it's OK not to do work when the stop() was invoked right after the continue() method, would be the code threadsafe?
class MyClass {
private volatile boolean stopped;
public void doWork() {
while(!stopped) {
doSmth();
}
}
public void stop() {
stopped = true;
}
public void continue() {
stopped = false;
}
}
As for me, it should. Could you please clarify if I'm wrong?
volatile simply ensures that changes to the variable are available to all threads.
The background: a thread may make local copies of shared variables. Synchronizing the values of these local variables with the global shared variables is what volatile effects.
However that does not synchronize in the java sence of a single entry, monitor/critical region.
The entire toolchest of java.util.concurrent offers things like ensuring that only one thread may change the value and such. If you want to start from ground up, one can with two variables do some blocking things: search for Dijkstra algorithms.
Here I think AtomicBoolean might be nice for non-blocking usage.
If you want to achieve to have a global boolean state that pauses resp. resumes threads when toggled (your stopped), instead of some ugly busy wait:
public void run () {
while (true) {
doWork();
try {
barrier.await();
} catch (InterruptedException | BrokenBarrierException ex) {
return;
}
}
}
Using a global CyclicBarrier - not the nicest API as it works with N predefined Runnables.
Related
Can someone please explain to me what I am missing: when I call Thread.sleep(1000) I suppose both threads should be executed in 1s so after that why should I make doSlice false to stop threads in 1s
why Thread.sleep() just doesn't stop them in 1s. I mean after 1s run method even shouldn't be called to check while condition:
public class ExecutionScheduling extends Thread{
public int slice_count=0;
public boolean doSlice=true;
public String name;
public ExecutionScheduling(String name){
this.name=name;
}
public void run() {
while (doSlice) {
slice_count++;
System.out.println(name);
}
}
public static void main(String[] args) throws InterruptedException {
ExecutionScheduling executionScheduling=new ExecutionScheduling("ex");
ExecutionScheduling executionScheduling1=new ExecutionScheduling("ex1");
executionScheduling.start();
executionScheduling1.start();
Thread.sleep(1000);
executionScheduling.doSlice=false;
executionScheduling1.doSlice=false;
System.out.println("ex: "+executionScheduling.slice_count);
System.out.println("ex1: "+executionScheduling1.slice_count);
}
}
Can someone please explain to me what I am missing
What you are missing is memory synchronization between the threads. When you start your 2 background threads, they have their own local memory (on their own CPUs) and you need to specifically update any shared data between them.
What is complicating the code is that System.out.println(...) is a synchronized method so it is giving you some memory synchronization "for free" but you shouldn't depend on it (see below). This means that if you removed that debug code, your program is going to be behave differently. Be careful of any usage of System.out.print* in threaded code.
Thread.sleep(1000);
When you run this sleep command, it will cause the main thread to go to sleep but the 2 background threads continue to run. They are each updating their own copy of slice_count but there is no guarantee that the main thread will see these updates.
// need to add the volatile keyword here
private volatile int slice_count;
By adding the volatile Java keyword to slice_count, this marks the field as being accessed by multiple threads. When the main thread the accesses slice_count, it will read the most updated value of it. You might also want to look into AtomicInteger which wraps a volatile int but allows multiple threads to do stuff like incrementAndGet().
Another place where you have memory sync issues is:
executionScheduling.doSlice = false;
executionScheduling1.doSlice = false;
So the doSlice field also needs to be volatile:
// need to add the volatile keyword here
public volatile boolean doSlice = true;
And lastly, in no order:
Your fields should be private if at all possible.
It should be executionScheduling1 and executionScheduling2.
It is a better pattern to define a Runnable instead of a Thread. See: https://stackoverflow.com/a/541527/179850
You might consider doing a join() to wait or each of the threads to finish their work before you print out their results.
// set the doSlices to false
executionScheduling.join()
executionScheduling1.join()
// printf results
If you add the join() calls then this will handle the memory synchronization for you in terms of slice_count so those no longer need to be volatile as long as you access them after the join() calls finish. Yes this is confusing. Thread coding is non-trivial. You will still need the doSlice fields to be volatile because they are accessed before join() finishes.
I hope I can understandably describe the situation.
I want to start some amount of threads and all of them will execute one synchronized method. Consider first thread checks value of a variable in this method then the lock will be released after check.Then the second thread calls the same function. But first thread will then (after some ms) modify this variable which is in another class but second thread will (maybe) check the variable before the first changed it. How can I force the second thread to wait (without sleep) till the first has finished and changed the variable before the second checks the value? Can the first send some signal like "variable changed, u can check it now"?
Now I try to write this in code: threads started all all do this run:
abstract class Animal {
protected House house;
abstract boolean eating();
#Override
public void run() {
try {
while(!Thread.interrupted()) {
if(eating()) {
goEat();//here house.eatingRoom.count will be changed
Thread.sleep(1000);
goback();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
All of them access this method:
class Cat extends Animal {
#Override
synchronized boolean eating() {
if (house.eatingRoom.count == 0)
return true;//first thread release lock and 2 thread access it but the value is not changed yet
else
return false;
}
}
And:
class EatingRoom {
final Set<Animal> count = new HashSet<>();
synchronized void add(Cat c) {
count.add(c);
}
}
to complete:
public class House extends Thread {
final EatingRoom eatingRoom = new EatingRoom();
//start all threads here so run in Animal class is executed..
}
The problem you are describing sounds like you could benefit from the Java synchronisation primitives like Object.wait and Object.notify.
A thread that owns the lock/monitor of a given object (such as by using the synchronized keyword) can call wait instead of looping and sleeping in a busy/wait pattern like you have in while(!Thread.interrupted()) which may waste many CPU cycles.
Once the thread enters the wait state it will release the lock it holds, which allows another thread to acquire that same lock and potentially change some state before then notifying one or more waiting threads via notify/notifyAll.
Note that one must be careful to ensure locks are acquired and released in the same order to help avoid deadlock scenarios when more than one lock is involved. Consider also using timeouts when waiting to ensure that your thread doesn't wait indefinitely for a condition that might never arise. If there are many waiting threads when you call notify be aware that you might not know which thread will be scheduled but you can set a fairness policy to help influence this.
Depending on the structure of your code you may be able to avoid some of the lower level primitives like synchronised blocks by using some higher level APIs such as https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/locks/Lock.html or keywords like volatile for variables that contain shared mutable state (like a condition you want to wait for to ensure the result of a write is observed on a subsequent read in a "happens before" relationship.
I have boolean field:
private boolean isReady = false;
private boolean isReady() {
return isReady;
}
and I am using it inside two methods:
synchronized (topologyLock)
{
try
{
while(!instance.isReady())
{
topologyLock.wait();
}
}
catch (InterruptedException e)
{
Thread.currentThread().interrupt();
}
private synchronized boolean topologyChanged()
{
synchronized(topologyLock)
{
isReady = true;
topologyLock.notifyAll();
}
}
I think that above code should work perfectly - or do I need to make this boolean variable volatile?
Quoting from stone ages:
So, when to make a variable volatile?
When you have a variable which can be accessed by many threads and you want every thread to get the latest updated value of that variable even if the value is updated by any other thread/process/outside of the program.
So one could think that volatile is necessary here. But (as Kayaman pointed out correctly): it is all about the Java memory model. And the fact that synchronized not only prevents race conditions (as only one thread can update data at any point in time) but also establishes a happens before relation.
Therefore: the above code doesn't have race conditions; and it also makes sure that each thread sees the "correct" value of isReady.
Of course, if you ever happen to manipulate isReady out of a synchronized block, then all bets are off.
No, as you are only interacting with it in synchronized blocks, which by definition run only on one thread.
If the code that you exported is the only code accessing isReady, it is correct.
Instead if this is the only part of code writing isReady, you need to define isReady as volatile to read it correctly from another part of code.
In any case if the relevant synchronized code is the code that you posted, is incorrect defining the method topologyChanged as synchronized because internally you are using the monitor topologyLock. It is enough.
Small question about memory visibility.
CodeSample1:
class CustomLock {
private boolean locked = false;
public boolean lock() {
if(!locked) {
locked = true;
return true;
}
return false;
}
}
This code is prone to bugs in a multi-threaded environment, first because of the "if-then-act" which is not atomic, and second because of potential memory visibility issues where for example threadA sets the field to true, but threadB that later wishes to read the field's value might not see that, and still see the value false.
The simplest solution is to use the synchronized keyword, as in CodeSample2.
CodeSample2:
class CustomLock {
private boolean locked = false;
public synchronized boolean lock() {
if(!locked) {
locked = true;
return true;
}
return false;
}
}
Now what if I wish to use an atomic variable, and for the example, an AtomicBoolean (question applies to all atomic variables),
CodeSample3:
public static class CustomLock {
private AtomicBoolean locked = new AtomicBoolean(false);
public boolean lock() {
return locked.compareAndSet(false, true);
}
}
Better performance considerations aside, we can see that now we've implemented similar logic to the "if-then-act" from CodeSample1, using AtomicBoolean.
It doesn't really matter what the code does logically, the question I have is what if 2 threads invoke the lock() method in CodeSample3 right about the same time, while it's clear that any write operation to the field will now be done atomically, does the use of AtomicBoolean also guarantees memory visibility?
Sorry for the long story, just wanted to make sure I'm coming across as clear as possible, Thanks guys...
Yes, according to the javadocs it guarantees:
compareAndSet and all other read-and-update operations such as getAndIncrement have the memory effects of both reading and writing volatile variables.
the question I have is what if 2 threads invoke the lock() method in CodeSample3 right about the same time, while it's clear that any write operation to the field will now be done atomically, does the use of AtomicBoolean also guarantees memory visibility?
For AtomicBoolean to handle multiple operations from different threads at the same time it has to guarantee memory visibility. It can make the guarantee because it wraps a volatile field. It is the language semantics of the volatile which ensures that memory barriers are crossed so that multiple threads see the most up to date value and that any updates will be published to main memory.
Btw, your lock(...) method should ready be tryLock(...) because it might not get the lock.
As you can tell I'm new to multithreading and a bit stuck here. For my program I need a thread (PchangeThread in the below example) that can be toggled on and off from another thread at any point during execution of the program.
The thread should be suspended on start and resume when pixelDetectorOn() is called.
The two threads will most likely not need to share any data except for a start/stop flag. I included a reference to the main thread anyway, just in case.
However, in the below code the only message that is ever output is "before entering loop", which indicates that the thread never wakes up from wait() for some reason. I'm guessing this is some kind of locking problem but I haven't been able to figure out what exactly is going wrong. Locking on this.detector from the main thread gives me the same result. Also I'm wondering if the wait()/notify() paradigm is really the way to go for suspending and waking the thread.
public class PchangeThread extends Thread {
Automation _automation;
private volatile boolean threadInterrupted;
PchangeThread(Automation automation)
{
this._automation = automation;
this.threadInterrupted = true;
}
#Override
public void run()
{
while (true) {
synchronized (this) {
System.out.println("before entering loop");
while (threadInterrupted == true) {
try {
wait();
System.out.println("after wait");
} catch (InterruptedException ex) {
System.out.println("thread2: caught interrupt!");
}
}
}
process();
}
}
private void process()
{
System.out.println("thread is running!");
}
public boolean isThreadInterrupted()
{
return threadInterrupted;
}
public synchronized void resumeThread()
{
this.threadInterrupted = false;
notify();
}
}
resumeThread() is called from the main thread the following way:
public synchronized void pixelDetectorOn(Context stateInformation) {
this.detector.resumeThread();
}
detector is a reference to an instance of PchangeThread.
The "detector"-thread is instantiated in the program's main module the following way:
detector=new PchangeThread(this);
As you said, you need to protect access to the shared flag. You declared threadInterrupted volatile, but than are still using syncronized. You only need one. I prefer to just use syncronized as it makes things simpler. Multi-threading is complicated enough, keep it simple unless you know you need more complicated controls. This means that any time threadInterrupted is read or written to, the access should be synchronized. Currently, you are not doing that in setThreadInterrupt() and isThreadInterrupted().
Secondly, you want to synchronize on as small of a code block as possible. Inside of run(), you are synchronizing over the inner loop. In actuality, you only need to to synchronize on the read of threadInterrupted. When the implementation of isThreadInterrupted() is fixed as mentioned above, you can use that directly and remove the synchronized block from the inner loop.
The fact that you are synchronizing on the inner loop, is the error that is causing your code to never print "thread is running!". PchangeThread acquires the lock on itself and calls wait() to suspend the thread. However, the thread is still holding the lock at this point. At some point later, the main thread calls resumeThread() in order to restart the thread. However, that method can not begin its execution because it must first wait to acquire the lock. However, it will never get the lock until the PchangeThread is notified.
You are providing two ways to set threadInterrupted, but only one of them notifies the thread when the value is set to false. Do you really need setThreadInterrupt()? I expect you don't. If you keep it, it should act the same as resumeThread() when the argument is false.
Lastly, it is better to lock on a private object instead of the instance itself. You have complete control over the private lock object. However, anyone with a reference to your thread instance could also use it as the lock for a synchronized block, which could potentially lead to a hard to find deadlock.
Your code altered to use my edits:
public class PchangeThread extends Thread {
private final Object _lock = new Object();
Automation _automation;
private final boolean _threadInterrupted;
PchangeThread(Automation automation)
{
_automation = automation;
_threadInterrupted = true;
}
#Override
public void run()
{
while (true) {
System.out.println("before entering loop");
while (isThreadInterrupted()) {
try {
wait();
System.out.println("after wait");
} catch (InterruptedException ex) {
System.out.println("thread2: caught interrupt!");
}
}
process();
}
}
private void process()
{
System.out.println("thread is running!");
}
public boolean isThreadInterrupted()
{
synchronized (_lock) {
return _threadInterrupted;
}
}
public void resumeThread()
{
synchronized (_lock) {
_threadInterrupted = false;
notify();
}
}
}
I personally would ask myself the following question in this case: Is the
isInterrupted
flag set only by the main thread e.g. the worker thread just reads it and decides whether to wait or not based on the flag BUT doesn't update it. Or can it be set by both the main thread and the worker thread.
If it is the former - go for a volatile boolean. That way the worker thread will not cache the volatile's value and will always read it from memory. This won't create a race condition because only 1 thread will be updating it - the main one. Think of it as a publish/subscribe scenario.
If you scenario falls in the latter category - use an AtomicBoolean variable. Both cases are going to be more efficient than the synchronized keyword, since you won't acquire any locks but in the case of Atomic* variables you will be utilizing CAS operations which are more lightweight than lock acquisition.
Your code is not wrong (though is not ideal).
I ran it and it prints all the expected messages. Likely, you just do not invoke resumeThread().
A couple of advises:
do not sync on Thread, make a Runnable and sync on it.
you want to start some computation, but what are the data to compute? Looks like they go in a separate way. This is a ground for errors. Use single channel for both data and control. The preferred way is to use a Queue for such a channel. For example, LinkedBlockingQueue is already synchronized in a proper way.
I doubt that anyone will read this, but just in case someone's interested in knowing:
When I checked the debugger log I noticed something strange - it read "debugging stopped on uncompilable source code: )Void;". Since I couldn't think of anything in my source that could have caused this error , I guessed that Netbeans had a problem with some part of the external code I was using (it was not caused by a breakpoint and the project compiled fine!). So, I just updated the third party library I'm using to it's latest version. And behold: after that I suddenly got a null pointer exception when I called resumeThread()!. I checked the rest of my code and quickly found the bug (indeed the reference to the thread was null).
So, to sum it up: The strange behaviour was caused by a minor bug in my program, but something in the external jar led to the suppression of the exception that should have been thrown. Just out of curiosity I double checked by downgrading the jar and "unfixing" the bug and again, the exception was swallowed and the debugger exited with the above mentioned strange message.
Netbeans version 7.1.1