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.
Related
In the following scenario, the boolean 'done' gets set to true which should end the program. Instead the program just keeps going on even though the while(!done) is no longer a valid scenario thus it should have halted. Now if I were to add in a Thread sleep even with zero sleep time, the program terminates as expected. Why is that?
public class Sample {
private static boolean done;
public static void main(String[] args) throws InterruptedException {
done = false;
new Thread(() -> {
System.out.println("Running...");
int count = 0;
while (!done) {
count++;
try {
Thread.sleep(0); // program only ends if I add this line.
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
Thread.sleep(2000);
done = true; // this is set to true after 2 seconds so program should end.
System.out.println("Done!"); // this gets printed after 2 seconds
}
}
EDIT: I am looking to understand why the above needs Thread.sleep(0) to terminate. I do not want to use volatile keyword unless it is an absolute must and I do understand that would work by exposing my value to all threads which is not my intention to expose.
Each thread have a different cached version of done created for performance, your counter thread is too busy making the calculations for count that it doesnt give a chance to reload done.
volatile ensures that any read/write is done on the main memory, always update the cpu cache copy.
Thread.sleep always pause the current thread, so even if 0 your counter thread is interrupted by some time <1ms, that is enough time for the thread to be adviced of done variable change.
I am no Java expert man, I don't even program in java, but let me try.
A thread on stackoverflow explains the Java Memory model: Are static variables shared between threads?
Important part: https://docs.oracle.com/javase/6/docs/api/java/util/concurrent/package-summary.html#MemoryVisibility
Chapter 17 of the Java Language Specification defines the
happens-before relation on memory operations such as reads and writes
of shared variables. The results of a write by one thread are
guaranteed to be visible to a read by another thread only if the write
operation happens-before the read operation. The synchronized and
volatile constructs, as well as the Thread.start() and Thread.join()
methods, can form happens-before relationships.
If you go through the thread, it mentions the "Happens before" logic when executing threads that share a variable. So my guess is when you call Thread.sleep(0), the main thread is able to set the done variable properly making sure that it "Happens first". Though, in a multi-threaded environment even that is not guaranteed. But since the code-piece is so small it makes it work in this case.
To sum it up, I just ran your program with a minor change to the variable "done" and the program worked as expected:
private static volatile boolean done;
Thank you. Maybe someone else can give you a better explanation :P
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.
I read it from Java Concurrency in Practice, that it is bad to share variables in threads without synchronisation. However, for some examples as following which only have one read thread and one write thread, I can't find errors in it. From my perspective, the result for the following program will definitely terminate and print 42 because ReaderThread can go through only when ready becomes true, and that means number is 42. Could somebody give me some explanation why I am wrong?
public class NoVisibility {
private static boolean ready;
private static int number;
private static class ReaderThread extends Thread {
public void run() {
while (!ready)
Thread.yield();
System.out.println(number);
}
}
public static void main(String[] args) {
new ReaderThread().start();
number = 42;
ready = true;
}
}
Since ready isn't volatile, there's no guarantee that ReaderThread will see that your main thread has changed it. When you mark ready as volatile, all writes from one thread will be seen in other threads reading it.
You always need some sort of synchronization / visibility control when communicating between threads. Whether it's volatile, explicitly using synchronized or using the java.util.concurrent.* classes.
You don't need synchronization (e.g., synchronized) in your example (though you do need volatile, more below) because reads and writes of boolean and int variables are always atomic. Which is to say, a thread can't be part-way through writing to a boolean (or int) variable when another thread comes along and reads it, getting garbage. The value being written by one thread is always fully written before another thread can read it. (This is not true of non-volatile double or long variables; it would be entirely possible for a thread to read garbage if it happened to read in the middle of another thread's write to a long or double if they aren't marked volatile.)
But you do need volatile, because each thread can have its own copy of the variables, and potentially can keep using its own copy for a long period of time. So it's entirely possible for your reader thread to wait forever, because it keeps re-reading its own copy of ready which stays false even though your main thread writes true to its copy of ready. It's also possible for your reader thread to see ready become true but keep reading its own copy of number, and so print 0 instead of 42.
You would need to use synchronized if you were modifying the state of an object that doesn't guarantee thread-safe access. For instance, if you were adding to a Map or List. That's because there are multiple operations involved, and it's essential to prevent one thread from reading a half-complete change another thread is making.
Other classes, such as those in java.util.concurrent, offer classes with thread-safe access semantics.
By referring to http://www.javamex.com/tutorials/synchronization_volatile.shtml, I am not sure whether I need to use volatile keyword in the following case, due to additional rule 3.
A primitive static variable will be write by Thread A.
The same primitive static variable will be read by Thread B.
Thread B will only run, after Thread A is "dead". ("dead" means, the last statement of Thread A's void run is finished)
Will the new value written by Thread A, will always committed to main memory, after it "dead"? If yes, does it mean I need not volatile keyword if the above 3 conditions are meet?
I am doubt that volatile is being required in this case. As it is required, then ArrayList may broken. As one thread may perform insert and update size member variable. Later, another thread (not-concurrently) may read the ArrayList's size. If you look at ArrayList source code, size is not being declared as volatile.
In JavaDoc of ArrayList, then only mention that ArrayList is not safe to be used for multiple threads access an ArrayList instance concurrently, but not for multiple threads access an ArrayList instance at different timing.
Let me use the following code to issulate this problem
public static void main(String[] args) throws InterruptedException {
// Create and start the thread
final ArrayList<String> list = new ArrayList<String>();
Thread writeThread = new Thread(new Runnable() {
public void run() {
list.add("hello");
}
});
writeThread.join();
Thread readThread = new Thread(new Runnable() {
public void run() {
// Does it guarantee that list.size will always return 1, as this list
// is manipulated by different thread?
// Take note that, within implementation of ArrayList, member
// variable size is not marked as volatile.
assert(1 == list.size());
}
});
readThread.join();
}
Yes, you still need to use volatile (or some other form of synchronization).
The reason why is that the two threads could run on different processors and even if one thread has long finished before the other starts there is no guarantee that the second thread will get the freshest value when it makes the read. If the field is not marked as volatile and no other synchronization is used, then the second thread could get a value that was cached locally on the processor it is running on. That cached value could in theory be out-of-date for a long period of time, including after the first thread completed.
If you use volatile the value will always be written to and read from main memory, bypassing the processor's cached value.
No, you may not need it. despite Mark Byers answer begin fairly accurate, it is limited. synchronized and volatile are not the only ways to correctly pass data between threads. there are other, less talked about "synchronization points". specifically, thread start and thread end are synchronization points. however, the thread which is starting Thread B must have recognized that Thread A is finished (e.g. by joining the thread or checking the thread's state). if this is the case, the the variable does not need to be volatile.
Possibly yes, unless you manually create a memory barrier. If A sets the variable, and B decides to take oit from some registry, you have a problem. So, you need a mmemory barrier, either implicit (lock, volatile) or explicit.
http://java.sun.com/docs/books/jls/third_edition/html/memory.html#17.4.4
The final action in a thread T1
synchronizes-with any action in
another thread T2 that detects that T1
has terminated. T2 may accomplish this
by calling T1.isAlive() or T1.join().
So it is possible to achieve your goal without using volatile.
In many cases, when there are apparent time dependencies, synchronization is being done by someone under the hood, and application doesn't need extra synchronization. Unfortunately this is not the rule, programmers must analyze each case carefully.
One example is Swing worker thread. People would do some calculation in a worker thread, save the result to a variable, then raise an event. The event thread will then read the result of the calculation from the variable. No explicit synchronization is needed from application code, because "raising an event" already did synchronization, so writes from worker thread is visible from event thread.
On one hand, this is a bliss. On the other hand, many people didn't understand this, they omit the synchronization simply because they never thought about the issue. Their programs happen to be correct... this time.
If Thread A definitely dies before Thread B starts reading then it would be possible to avoid using volatile
eg.
public class MyClass {
volatile int x = 0;
public static void main(String[] args) {
final int i = x;
new Thread() {
int j = i;
public void run() {
j = 10;
final int k = j;
new Thread() {
public void run() {
MyClass.x = k;
}
}.start();
}
}.start();
}
}
However, the problem is that whichever Thread starts Thread B will need to now that the value that Thread A is writing to has changed and to not use its own cached version. The easiest way to do this is to get Thread A to spawn Thread B. But if Thread A has nothing else to do when it spawns Thread B then this seems a little pointless (why not just use the same thread).
The other alternative is that if no other thread is dependent on this variable then maybe Thread A could initial a local variable with the volatile variable, do what it needs to do, and then finally write the contents of its local variable back to the volatile variable. Then when Thread B starts it initialises its local variable from the volatile variable and reads only from its local variable thereafter. This should massively reduce the amount of time spent keeping the volatile variable in sync. If this solution seems unacceptable (because of other threads writing to the volatile variable or whatever) then you definitely need to declare the variable volatile.
I'm trying to figure out if the code below suffers from any potential concurrency issues. Specifically, the issue of visibility related to volatile variables. Volatile is defined as: The value of this variable will never be cached thread-locally: all reads and writes will go straight to "main memory"
public static void main(String [] args)
{
Test test = new Test();
// This will always single threaded
ExecutorService ex = Executors.newSingleThreadExecutor();
for (int i=0; i<10; ++i)
ex.execute(test);
}
private static class Test implements Runnable {
// non volatile variable in question
private int state = 0;
#Override
public void run() {
// will we always see updated state value? Will updating state value
// guarantee future run's see the value?
if (this.state != -1)
this.state++;
}
}
For the above single threaded executor:
Is it okay to make test.state non volatile? In other words, will every successive Test.run() (which will occur sequentially and not concurrently because again executor is single threaded), always see the updated test.state value? If not, doesn't exiting of Test.run() ensure any changes made thread locally get written back to main memory? Otherwise when does changes made thread locally get written back to main memory if not upon exiting of the thread?
As long as it's only a single thread there is no need to make it volatile. If you're going to use multiple threads, you should not only use volatile but synchronize too. Incrementing a number is not an atomic operation - that's a common misconception.
public void run() {
synchronize (this) {
if (this.state != -1)
this.state++;
}
}
Instead of using synchronization, you could also use AtomicInteger#getAndIncrement() (if you won't need an if before).
private AtomicInteger state = new AtomicInteger();
public void run() {
state.getAndIncrement()
}
Originally, I was thinking this way:
If the task were always executed by
the same thread, there would be no
problem. But Excecutor produced by
newSingleThreadExecutor() may create
new threads to replace a those that
are killed for any reason. There is no
guarantee about when the replacement
thread will be created or which thread
will create it.
If a thread performs some writes, then
calls start() on a new thread, those
writes will be visible to the new
thread. But there is no guarantee that
that rule applies in this case.
But irreputable is right: creating a correct ExecutorService without sufficient barriers to ensure visibility is practically impossible. I was forgetting that detecting the death of another thread is a synchronizes-with relationship. The blocking mechanism used to idle worker threads would also require a barrier.
Yes it is safe, even if the executor replaced its thread in the middle. Thread start/terminate are also synchronization points.
http://java.sun.com/docs/books/jls/third_edition/html/memory.html#17.4.4
A simple example:
static int state;
static public void main(String... args) {
state = 0; // (1)
Thread t = new Thread() {
public void run() {
state = state + 1; // (2)
}
};
t.start();
t.join();
System.out.println(state); // (3)
}
It is guaranteed that (1), (2), (3) are well ordered and behave as expected.
For the single thread executor, "Tasks are guaranteed to execute sequentially", it must somehow detect the finish of one task before starting the next one, which necessarily properly synchronizes the different run()'s
Your code, specifically this bit
if (this.state != -1)
this.state++;
would require the atomic test of the state value and then an increment to the state in a concurrent context. So even if your variable was volatile and more than one thread was involved, you would have concurrency issues.
But your design is based on asserting that there will always only be one instance of Test, and, that single instance is only granted to a single (same) thread. (But note that the single instance is in fact a shared state between the main thread and the executor thread.)
I think you need to make these assumptions more explicit (in the code, for example, use the ThreadLocal and ThreadLocal.get()). This is to guard both against future bugs (when some other developer may carelessly violate the design assumptions), and, guard against making assumptions about the internal implementation of the Executor method you are using which may in some implementations simply provide single threaded executor (i.e. sequential and not necessarily the same thread in each invocation of execute(runnable).
It is perfectly fine for state to be non-volatile in this specific code, because there is only one thread, and only that thread accesses the field. Disabling caching the value of this field within the only thread you have will just give a performance hit.
However if you wish to use the value of state in the main thread which is running the loop, you have to make the field volatile:
for (int i=0; i<10; ++i) {
ex.execute(test);
System.out.println(test.getState());
}
However, even this might not work correctly with volatile, because there is no synchronization between the threads.
Since the field is private, there is only an issue if the main thread executes a method that can access this field.
If your ExecutorService is single threaded then there is no shared state, so I don't see how there could be any issues around that.
However wouldn't it make more sense to pass a new instance of your Test class to each call to execute()? i.e.
for (int i=0; i<10; ++i)
ex.execute(new Test());
This way there will not be any shared state.