I was trying impact of thread priority and when println in run method stays in comment both threads end in the same time and I don't understand this behavior, can you explain ? Thank you.
Main.class
public class Main {
public static void main(String[] args) {
Test t1 = new Test("Thread #1");
Test t2 = new Test("Thread #2");
t1.thread.setPriority(10);
t2.thread.setPriority(1);
t1.thread.start();
t2.thread.start();
try {
t1.thread.join();
t2.thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(t1.thread.getName() + ": " + t1.count);
System.out.println(t2.thread.getName() + ": " + t2.count);
System.out.println("End of main thread.");
}
}
Test.class
public class Test implements Runnable{
public Thread thread;
static boolean stop = false;
int count = 0;
public Test(String name){
thread = new Thread(this, name);
}
#Override
public void run(){
for(int i = 0; i < 10000000 && stop == false; i++){
count = i;
//System.out.println(count + " " + thread.getName());
}
stop = true;
System.out.println("End of " + thread.getName());
}
}
without println with println
End of Thread #1 End of Thread #1
End of Thread #2 End of Thread #2
Thread #1: 9999999 Thread #1: 9999999
Thread #2: 9999999 Thread #2: 3265646
End of main thread. End of main thread.
Your two threads access a shared mutable variable without proper synchronization. In this case, there is no guaranty about when (or whether at all) a thread will learn about a change made by another thread. In your case, the change made by one thread is not noticed by the other at all. Note that while for a primitive data type like boolean, not reading the up to date value is the worst thing that can happen, for non-primitive data types, even worse problems, i.e. inconsistent results could occur.
Inserting a print statement has the side effect of synchronizing the threads, because the PrintStream perform an internal synchronization. Since there is no guaranty that System.out will contain such a synchronizing print stream implementation, this is an implementation specific side-effect.
If you change the declaration of stop to
static volatile boolean stop = false;
the threads will re-read the value from the shared heap in each iteration, reacting immediately on the change, at the cost of reduced overall performance.
Note that there are still no guarantees that this code works as you expect, as there is no guaranty about neither, that the thread priority has any effect nor that threads run in parallel at all. Thread scheduling is implementation and environment dependent behavior. E.g. you might find out that not the thread with the highest priority finishes its loop first, but just the thread that happened to be started first.
To clarify: the only purpose of thread/process "priority," in any language environment on any operating system, is to suggest to the OS "which of these two 'ought to be, I think, run first'," if both of them happen to be instantaneously "runnable" and a choice must be made to run only one of them.
(In my experience, the best example of this in-practice is the Unix/Linux nice command, which voluntarily reduces the execution-priority of a command by a noticeable amount.) CPU-intensive workloads which perform little I/O can actually benefit from being given a reduced priority.
As other answerers have already stressed, it is impossible to predict "what will actually happen," and priority can never be used to alter this premise. You must explicitly use appropriate synchronization-primitives to assure that your code executes properly in all situations.
Related
Like this, I have two thread. The SleepRunner thread add some random numbers to a list then change flag to true and sleep. The main thread wait SleepRunner thread until the flag in SleepRunner object change from false to true then main thread will interrupte SleepRunner thread and the program will end.
But the question is, when the while loop is no body code in main thread, the variable 'runner' is not updated inside loop in other words The program is not over after SleepRunner thread change flag from false to true. So I tried to use debug tools in idea, but the program ended smoothly. And If I write some code, like System.out.println() or Thread.sleep(1) in while loop body at main thread, the program ended successfully too. it's too incredible! Does anyone know why this happens? Thanks.
public class Test1 {
public static void main(String[] args) {
SleepRunner runner = new SleepRunner();
Thread thread = new Thread(runner);
thread.start();
while(!(runner.isFlag())){
/*try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}*/
}
System.out.println("END");
thread.interrupt();
}
}
public class SleepRunner implements Runnable {
private boolean flag = false;
public boolean isFlag() {
return flag;
}
#Override
public void run() {
List<Integer> list = new ArrayList<>();
for (int i = 0; i < 100; i++) {
try {
Thread.sleep((long) (Math.random() * 200));
}
catch (InterruptedException e) {
System.out.println("Interrupted");
}
int num = (int) (Math.random() * 100);
System.out.println(Thread.currentThread().getName() + " " + num);
list.add(num);
}
flag = true;
System.out.println("30 Seconds");
try {
Thread.sleep(30000);
}
catch (InterruptedException e) {
System.out.println("Interrupted in 30 seconds");
}
System.out.println("sleep runner thread end");
}
}
You've violated the java memory model.
Here's how the JMM works*:
Each thread, whenever any field (from any object) is read or updated, flips a coin. On heads, it will make a copy and update/read from that. On tails, it won't. Your job is to ensure your code functions correctly regardless of how the coin lands, and you can't force the coinflip in a unit test. The coin need not be 'fair'. The coin's behaviour depends on the music playing in your music player, the whims of a toddler, and the phase of the moon. (In other words, any update/read may be done to a local cache copy, or not, up to the java implementation).
You may safely conclude that the only way to do it correctly, is to ensure the thread never flips that coin.
The way to accomplish that is to establish so-called 'comes before' relationships. Establishing them is done primarily by using synchronization primitives, or by calling methods that use synchronization primitives. For example, if I do this:
thread X:
synchronized(x) {
x.foo();
System.out.println(shared.y);
shared.y = 10;
}
thread Y:
synchronized(x) {
x.foo();
System.out.println(shared.y);
shared.y = 20;
}
then you've established a relationship: code block A comes before code block B, or vice versa, but you've at least established that they must run in order.
As a consequence, this will print either 0 10 or 0 20, guaranteed. Without the synchronized block, it can legally print 0 0 as well. All 3 results would be an acceptable result (the java lang spec says it's okay, and any bugs filed that you think this makes no sense would be disregarded as 'working as intended').
volatile can also be used, but volatile is quite limited.
Generally, because this cannot be adequately tested, there are only 3 ways to do threading properly in java:
'in the large': Use a webserver or other app framework that takes care of the multithreading. You don't write the psv main() method, that framework does, and all you write are 'handlers'. None of your handlers touch any shared data at all. The handlers either don't share data, or share it via a bus designed to do it right, such as a DB in serializable transaction isolation mode, or rabbitmq or some other message bus.
'in the small': Use fork/join to parallellize a giant task. The handler for the task cannot, of course, use any shared data.
read Concurrency in Practice (the book), prefer using the classes in the java.util.concurrent package, and in general be a guru about how this stuff works, because doing threading any other way is likely to result in you programming bugs which your tests probably won't catch, but will either blow up at production time, or will result in no actual multithreading (e.g. if you overzealously synchronize everything, you end up having all cores except one core just waiting around, and your code will actually run way slower than if it was just single threaded).
*) The full explanation is about a book's worth. I'm just giving you oversimplified highlights, as this is merely an SO answer.
I was going through the tutorial https://www.youtube.com/watch?v=SC2jXxOPe5E to understand how volatile variable works and came across a strange behavior.
For the following code snippet
public class VolatileDemo {
static boolean running = false;
public static void main(String a[]) throws InterruptedException {
Thread t = new Thread(new Runnable() {
#Override
public void run() {
while (!running) {
}
System.out.print("Started");
while (running) {
}
System.out.print("Stopped");
}
});
t.start();
Thread.sleep(1000);
running = true;
System.out.print("Starting ");
Thread.sleep(1000);
running = false;
System.out.print("Stopping");
}
}
The output is : Starting Stopping (which is understandable by video)
But for the following code snippet
public class VolatileDemo {
static boolean running = false;
public static void main(String a[]) throws InterruptedException {
Thread t = new Thread(new Runnable() {
#Override
public void run() {
while (!running) {
System.out.print("Flag " + running);
}
System.out.print(" Started");
while (running) {
System.out.print(" Flag " + running);
}
System.out.print(" Stopped");
}
});
t.start();
Thread.sleep(1000);
running = true;
System.out.print(" Starting");
Thread.sleep(1000);
running = false;
System.out.print(" Stopping");
}
}
The output is Flag: false Starting Started Flag: true Stopping Stopped(ignore the output)
My concern here is why the thread was able to read the updated value of 'running' in case 2?
Edit: The difference between the two snippets is the addition below statement in later case
System.out.print("Flag " + running);
I think it's important to understand what the purpose of volatile is.
On a multi-processor system with multiple levels of cache an update to a variable can take some time to reach main memory and hence other threads depending on latency and the hardware design. The code basically is supposed to demo this happening, the change to the running variable is changed and the output should show some delay between when it was changed and when the thread actually starts. Adding the volatile keyword should reduce this delay as it forces the write through to main memory to happen immediately instead of when the cache decides to do it.
Please note that volatile doesn't make code thread safe, it just tells the JVM that the variable needs to be written directly to main memory bypassing any delayed writing scheme the caching hardware might otherwise do. It also means that the variable is read from main memory so that stale data is not used. It is for reducing the latency between a variable being updated in one thread and seen to be updated in another. This isn't something you'll need often, and should use sparingly as bypassing the cache will have performance ramifications for your code.
When you've added extra instructions to the code of the thread you've effectively significantly reduced the rate at which it can poll the running variable. I'd say it's likely that the time between running being changed and being updated in main memory is very small, much quicker than the time it takes to output on the console (which takes longer than you'd think). So it is very likely that you won't see what you expect except on the rare occasion that the boolean evaluation in the while loop happens at the exact correct moment.
Unlike deadlock, this particular property of multi-processing is quite hard to demonstrate on a single machine. It's much more likely to happen on a NUMA system architecture (or a cluster) where the cache to memory update latency can be much larger. On a single system the time between a variable being updated in cache and written to main memory is very small.
I was expecting this code to be thread safe. I ran it a few times, but got different results. However, if I uncomment the sleep(1000) part, it prints 10000 every time (at least from the results from my test runs).
So what's wrong? Could it be something to do with thread.join()?
public class Test implements Runnable{
private int x;
public synchronized void run(){
x++;
}
public static void main(String args[]){
Test test = new Test();
Thread thread = null;
for (int i = 0; i < 10000; i++) {
thread = new Thread(test);
try {
thread.join();
} catch (InterruptedException e) {}
thread.start();
}
// try {
// Thread.sleep(1000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
System.out.println(test.x);
}
}
edit: oops, my bad. I misunderstood how Thread#join functions. And synchronizing on run() method is a bad idea.
thread.join() should be called after thread.start().
join() means "block until the thread finishes". That only makes sense after the thread has started.
Presumably your Thread.sleep() call actually waits long enough for all the threads (that you effectively didn't join) to finish. Without it, the threads might not all have finished when you print out the value of x.
There are two problems here:
a race condition where the main thread finishes before all the worker threads.
a memory visibility issue where the main thread is not guaranteed to see the updated value of x.
Thread#join is implemented using Object#wait. The condition variable used is the alive flag on the Thread:
groovy:000> new Thread().isAlive()
===> false
Thread.join is checking the alive flag before the thread has started, so isAlive returns false and join returns before the thread can start. The counter still gets incremented eventually, but since the join doesn't happen for that thread then the main thread may be printing out the results for x before all the threads can execute.
Adding the sleep gives all the threads enough time to finish up that x is what you expect by the time that the main thread prints it out.
In addition to the race condition, there is a memory visibility issue since the main thread is accessing x directly and is not using the same lock as the other threads. You should add an accessor to your Runnable using the synchronized keyword:
public class Test implements Runnable{
private int x;
public synchronized void run(){
x++;
}
public synchronized int getX() {
return x;
}
and change the main method to use the accessor:
System.out.println(test.getX());
Memory visibility issues may not be apparent since they depend on how aggressive the JVM is about caching and optimizing. If your code runs against a different JVM implementation in production, and you don't adequately guard against these issues, you may see errors there that you can't reproduce locally on a PC.
Using AtomicInteger would simplify this code and allow solving the memory visibility problem while removing synchronization.
You don't add synchronized to the run method. Each thread gets its own.
You have to synchronize the mutable, shared data. In your case, that's the integer x. You can synchronize get/set or use AtomicInteger.
This question already has an answer here:
Loop doesn't see value changed by other thread without a print statement
(1 answer)
Closed 7 years ago.
I have a simple TestThreadClientMode class to test a race condition. I tried two attempts:
When I run the following code with System.out.println(count); commented in the second thread, the output was:
OS: Windows 8.1
flag done set true
...
and the second thread was alive forever. Because the second thread never sees change of the done flag which was set true by Main thread.
When I uncommented System.out.println(count); the output was:
OS: Windows 8.1
0
...
190785
190786
flag done set true
Done! Thread-0 true
And the program stopped after 1 second.
How did System.out.println(count); make the second thread see the change in done?
Code
public class TestThreadClientMode {
private static boolean done;
public static void main(String[] args) throws InterruptedException {
new Thread(new Runnable() {
public void run() {
int count = 0;
while (!done) {
count ++;
//System.out.println(count);
}
System.out.println("Done! " + Thread.currentThread().getName() + " " + done);
}
}).start();
System.out.println("OS: " + System.getProperty("os.name"));
Thread.sleep(1000);
done = true;
System.out.println("flag done set true ");
}
}
This is a brilliant example of memory consistency errors. Simply put, the variable is updated but the first thread does not always see the variable change. This issue can be solved by making done variable volatile by declaring it like so:
private static volatile boolean done;
In this case, changes to the variable are visible to all threads and the program always terminates after one second.
Update: It appears that using System.out.println does indeed solve the memory consistency issue - this is because the print function makes use of an underlying stream, which implements synchronization. Synchronization establishes a happens-before relationship as described in the tutorial I linked, which has the same effect as the volatile variable. (Details from this answer. Also credit to #Chris K for pointing out the side effect of the stream operation.)
How did System.out.println(count); make the second thread see the change in done?
You are witnessing a side effect of println; your program is suffering from a concurrent race condition. When coordinating data between CPUs it is important to tell the Java program that you want to share the data between the CPUs, otherwise the CPUs are free to delay communication with each other.
There are a few ways to do this in Java. The main two are the keywords 'volatile' and 'synchronized' which both insert what hardware guys call 'memory barriers' into your code. Without inserting 'memory barriers' into the code, the behaviour of your concurrent program is not defined. That is, we do not know when 'done' will become visible to the other CPU, and it is thus a race condition.
Here is the implementation of System.out.println; notice the use of synchronized. The synchronized keyword is responsible for placing memory barriers in the generated assembler which is having the side effect of making the variable 'done' visible to the other CPU.
public void println(boolean x) {
synchronized (this) {
print(x);
newLine();
}
}
The correct fix for your program, is to place a read memory barrier when reading done and a write memory barrier on writing to it. Typically this is done by reading or writing to 'done' from within a synchronized block. In this case, marking the variable done as volatile will have the same net effect. You can also use an AtomicBoolean instead of boolean for the variable.
The println() implementation contains explicit memory barrier:
public void println(String x) {
synchronized (this) {
print(x);
newLine();
}
}
Which causes the invoking thread to refresh all variables.
The following code will have the same behavior as yours:
public void run() {
int count = 0;
while (!done) {
count++;
synchronized (this) {
}
}
System.out.println("Done! " + Thread.currentThread().getName() + " " + done);
}
In fact any object can be used for monitor, following will also work:
synchronized ("".intern()) {
}
Another way to create explicit memory barrier is using volatile, so the following will work:
new Thread() {
private volatile int explicitMemoryBarrier;
public void run() {
int count = 0;
while (!done) {
count++;
explicitMemoryBarrier = 0;
}
System.out.println("Done! " + Thread.currentThread().getName() + " " + done);
}
}.start();
The program creates thread t0 which spawns thread t1 and subsequently threads t2 and t3 are created.After the execution of thread t3and the application never returns to the other threads spawned earlier(t0,t1,t2) and they are left stuck.
Why are the threads t0, t1, and t2 suspended?
public class Cult extends Thread
{
private String[] names = {"t1", "t2", "t3"};
static int count = 0;
public void run()
{
for(int i = 0; i < 100; i++)
{
if(i == 5 && count < 3)
{
Thread t = new Cult(names[count++]);
t.start();
try{
Thread.currentThread().join();
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
System.out.print(Thread.currentThread().getName() + " ");
}
}
public static void main(String[] a`)
{
new Cult("t0").start();
}
}
The most important point you missed:
Thread.currentThread().join();
Method join in source code uses isAlive method.
public final synchronized void join(long millis)
...
if (millis == 0) {
while (isAlive()) {
wait(0);
}
...
}
It means that Thread.currentThread().join() will return only when Thread.currentThread() is dead.
But in your case it's impossible because of your running code in Thread.currentThread() has itself
this peace of code Thread.currentThread().join(). That's why after Thread 3 completion your program should hang and nothing happens thereafter.
Why are the threads t0, t1, and t2 suspended? The execution of thread t3 completes.
t3 completes because it is not trying to fork a 4th thread and therefore is not trying to join() with it's own thread. The following line will never return so t0, t1, and t2 all stop there and wait forever:
Thread.currentThread().join();
This is asking the current thread to wait for itself to finish which doesn't work. I suspect that you meant to say t.join(); which is waiting for the thread that was just forked to finish.
Here are some other thoughts about your code in no apparent order:
You should consider implements Runnable instead of extends Thread. See here: "implements Runnable" vs. "extends Thread"
You are using the shared static variable count in multiple threads without any protection of locking. The best solution is to use an AtomicInteger instead of a int. You probably don't have a problem here because each thread is modifying count and then forking another thread but if you tried to fork 2 threads, this would be a real problem because of data race conditions.
I'm not sure why you are only spawning another thread if(i == 5 && count < 3). i is only going to be 5 once in that loop. Is that really what you intended?
String[] names = {"t1", "t2", "t3"}; fields are recommended to be declared at the top of classes. Otherwise they get buried in the code and get lost.
In main you start a Cult thread and then the main thread finishes. This is unnecessary and you can just call cult.run(); in main instead and use the main thread.
Cult(String s) { super(s); } there is no point in having a constructor that calls the super constructor with the same arguments. This can be removed.
This is debatable but I tend to put main method at the top of the class and not bury it since it is the "entrance" method. Same thing with constructors. Those should be above the run() method.
catch(Exception e) {} is a really bad pattern. At the very least you should do a e.printStackTrace(); or log it somehow. Catching and just dropping exceptions hides a lot of problems. Also, catching Exception should be changed to catch(InterruptedException e). You want to restrict your catch blocks just the exceptions thrown by the block otherwise this may again hide problems in the future if you copy and paste that block somewhere.
More a good practice but never use constants like 3 that have to match another data item. In this case it would be better to use names.length which is 3. THis means that you don't need to change 2 places in the code if you want to increase the number of threads. You could also have the name be "t" + count and get rid of the names array altogether.