This question already has an answer here:
Loop doesn't see value changed by other thread without a print statement
(1 answer)
Closed 5 years ago.
I have theoretical question about memory visibility. Here is sample code:
public class TwoThreadApp {
private static class A {
int x = 1;
}
public static void main(String[] arg) throws InterruptedException {
A a = new A();
Thread t2 = new Thread(() -> {
while (true) {
if (a.x == 2) {
System.out.println(a.x);
return;
}
// IO operation which makes a.x visible to thread "t2"
System.out.println("in loop");
}
});
t2.start();
Thread.sleep(100);
a.x = 2;
}
}
Without System.out.println("in loop") programs works indefinitely, which is expected behavior.
But with System.out.println("in loop") it is always completes, which is not expected, because a.x is not volatile and there is no synchronized blocks.
My env: ubuntu 16.04, openjdk 1.8.0_131
Why it behaves this way?
Without System.out.println("in loop") programs works indefinitely, which is expected behavior.
On the contrary, the program should quit. The program keeps going, that is side-effect of fact that x is cached (as non volatile). The caching is compiler's optimalization and you should not rely on it (depending on JVM settings).
But with System.out.println("in loop") it is always completes, which is not expected, because a.x is not volatile and there is no synchronized blocks.
This is IMHO expected behaviour. I cannot tell you why, I'd assume the IO operations are involved to clear the thread cache (please comment/correct if someone is having better insight).
Accessing variables without synchronization or locks or being volatile with multiple threads may be really unpredictable.
You can even disable many optimalizations with -Djava.compiler=NONE (then the program should always quit as expected)
IMHO this is something to do with Compiler optimization I think. In your first example compile can decide to move the If condition outside while loop like
if(a.x == 2) while(true) {...}
In 2nd case as you are using println which internally uses synchronized keyword compiler may not optimize the code as above.
This is what I think and I maybe wrong.
Edit: You can also refer here : Loop doesn't see changed value without a print statement
Related
This question already has an answer here:
Loop doesn't see value changed by other thread without a print statement
(1 answer)
Closed 4 years ago.
So Im experimenting a bit with multithreading currently, since im still pretty new to Java. Now, I have multiple threads that all influence the same long variable. However, it seems that afer a while of not doing anything but checking the if statement the while loop just stops executing (as in, it loops infinitely). It does work if i just print something within the while-loop.
Does not work:
while(true){
if(longVariable < 2)
break;
}
Does somehow work:
while(true){
System.out.println("hi");
if(longVariable < 2)
break;
}
Why is this?
while(true){
if(longVariable < 2)
break;
}
In this code, there is no reason for the JVM to believe that longVariable will ever change. It can effectively rewrite it to:
long cached = longVariable;
while(true){
if(cached < 2)
break;
}
Which loops infinitely if longVariable is at least two when it executes, because nothing can change cached.
You have to give the compiler a hint that this rewrite isn't allowed. It works with the System.out.println on your JVM because it happens to be implemented with synchronization (which is common, but not required). This inserts memory barriers which means that the cached value of longVariable is invalidated, and has to be read again.
But it's not guaranteed to work. To make it work correctly, either declare the variable volatile:
volatile long longVariable
which prevents its value from being cached.
Or use something like an AtomicLong instead of a plain long variable.
Or, most onerously, use explicit synchronization (ensuring that all reads of and writes to the variable are synchronized on the same "something"):
long v;
synchronized (something) {
v = longVariable;
}
if (v < 2) ...
When you have a non volatile variable which is not updated by a thread, it is free to inline it.
In your first case, once the code has compiled by the JIT, it might no longer read the value and instead make the condition always true.
In the second case, you have a thread safe operation. println on System.out is a synchronized method. This adds a read and write barrier and prevents the JIT from optimising the read operation away.
If you try this, it should also work.
while(true){
synchronized("hi") { } // does nothing but add memory barriers.
if(longVariable < 2)
break;
}
It also slows down the code by more than 1000x so the method might not have been JITed by the time you try to stop the thread.
The simple solution is to make the variable volatile and it will be read in a thread safe manner every time.
I searched "java race condition" and saw a lot of articles, but none of them is what I am looking for.
I am trying to solve the race condition without using lock, synchronization, Thread.sleep something else. My code is here:
public class Test {
static public int amount = 0;
static public boolean x = false;
public static void main(String[] args) {
Thread a = new myThread1();
Thread b = new myThread2();
b.start();
a.start();
}
}
class myThread1 extends Thread {
public void run() {
for (int i = 0; i < 1000000; i++) {
if (i % 100000 == 0) {
System.out.println(i);
}
}
while(true){
Test.x = true;
}
}
}
class myThread2 extends Thread {
public void run() {
System.out.println("Thread 2: waiting...");
while (!Test.x) {
}
System.out.println("Thread 2: finish waiting!");
}
}
I expect the output should be:
Thread 2: waiting...
0
100000
200000
300000
400000
500000
600000
700000
800000
900000
Thread 2: finish waiting!
(Terminated normally)
But it actually is:
Thread 2: waiting...
0
100000
200000
300000
400000
500000
600000
700000
800000
900000
(And the program won't terminate)
After I added a statement to myThread2, changed
while (!Test.x) {
}
to
while (!Test.x) {
System.out.println(".");
}
The program terminate normally and the output is what I expected (except those ".')
I know when 2 threads execute concurrently, the CPU may arbitrarily switch to another before fetch the next instruction of machine code.
I thought it will be fine if one thread read a variable while another thread write to the variable. And I really don't get it why the program will not terminate normally. I also tried to add a Thread sleep statement inside the while loop of myThread1, but the program still will not terminate.
This question puzzled me few weeks, hope any one can help me please.
Try to declare x as volatile :
static public volatile boolean x = false;
Test.x isn't volatile and thus might not be synchronized between threads.
How the print-command in the second loop affects the overall behavior can't be predicted, but apparently in this case it causes x to be synchronized.
In general: if you omit all thread-related features of java, you can't produce any code, that has a well defined behavior. The minimum would be mark variables that are used by different threads as volatile and synchronize pieces of code, that my not run concurrently.
The shared variable x is being read and written from multiple threads without any synchronisation and hence only bad things can happen.
When you have the following,
while (!Test.x) {
}
The compiler might optimise this into an infinite loop since x (the non volatile variable) is not being changed inside the while loop, and this would prevent the program from terminating.
Adding a print statement will add more visibility since it has a synchronised block protecting System.out, this will lead into crossing the memory barrier and getting a fresh copy of Test.x.
You CAN NOT synchronise shared mutable state without using synchronisation constructs.
Much more better would be a LOCK object you may wait in Thread2 and send a notificytion in thread 1. You are currently active waiting in Thread2 and consume a lot of CPU resources.
Dummy code example:
main() {
Object lock = new Object();
Thread2 t2 = new Thread2(lock);
t2.start();
Thread1 t1 = new Thread1(lock);
t1.start();
...
}
class Thread1 {
Object lock = null;
public Thread1(Object lock) {
this.lock = lock;
...
}
public void run() {
...
synchronized (lock) {
lock.notifyAll();
}
}
} // end class Thread1
// similar Thread2
class Thread2 {
... constructor
public void run()
{
System.out.println("Thread 2: waiting...");
synchronized(lock) {
lock.wait();
}
System.out.println("Thread 2: finish waiting!");
}
....
This construct does not consume any CPU cycles without doing anything in "Thread2". You can create a custom number of "Thread2" instances and wait till "Thread1" is finished. You should "only" start all "Thread2" instances before "Thread1". Otherwise "Thread1" may finish before "Thread2" instances are started.
What you are really asking is, "Why does my program work as expected when I add a call to println()?"
Actions performed by one thread aren't generally required to be visible to other threads. The JVM is free to treat each thread as if it's operating in its own, private universe, which is often faster than trying to keep all other threads updated with events in that private universe.
If you have a need for some threads to stay up-to-date with some actions of another thread, you must "synchronize-with" those threads. If you don't, there's no guarantee threads will ever observe the actions of another.
Solving a race condition without a memory barrier is a nonsensical question. There's no answer, and no reason to look for one. Declare x to be a volatile field!
When you call System.out.println(), you are invoking a synchronized method, which, like volatile, acts as a memory barrier to synchronize with other threads. It appears to be sufficient in this case, but in general, even this is not enough to guarantee your program will work as expected. To guarantee the desired behavior, the first thread should acquire and release the same lock, System.out, after setting x to true.
Update:
Eric asks, "I am curious how volatile work, what has it done behind. I thought that everything can be created by addition, subtraction, compare, jumping, and assignment."
Volatile writes work by ensuring that values are written to a location that is accessible to all reading threads, like main memory, instead of something like a processor register or a data cache line.
Volatile reads work by ensuring that values are read from that shared location, instead of, for example, using a value cached in a register.
When Java byte codes are executed, they are translated to native instructions specific to the executing processor. The instructions necessary to make volatile work will vary, but the specification of the Java platform require that whatever the implementation, certain guarantees about visibility are met.
I am new to Java, I am currently learning about volatile. Say I have the following code:
public class Test
{
private static boolean b = false;
public static void main(String[] args) throws Exception
{
new Thread(new Runnable()
{
public void run()
{
while(true)
{
b = true;
}
}
}).start();
// Give time for thread to start
Thread.sleep(2000);
System.out.println(b);
}
}
Output:
true
This code has two threads (the main thread and another thread). Why is the other thread able to modify the value of b, shouldn't b be volatile in order for this to happen?
The volatile keyword guarantees that changes are visible amongst multiple threads, but you're interpreting that to mean that opposite is also true; that the absence of the volatile keyword guarantees isolation between threads, and there's no such guarantee.
Also, while your code example is multi-threaded, it isn't necessarily concurrent. It could be that the values were cached per-thread, but there was enough time for the JVM to propagate the change before you printed the result.
You are right that with volatile, you can ensure/guarantee that your 2 threads will see the appropriate value from main memory at all times, and never a thread-specific cached version of it.
Without volatile, you lose that guarantee. And each thread is working with its own cached version of the value.
However, there is nothing preventing the 2 threads from resynchronizing their memory if and when they feel like it, and eventually viewing the same value (maybe). It's just that you can't guarantee that it will happen, and you most certainly cannot guarantee when it will happen. But it can happen at some indeterminate point in time.
The point is that your code may work sometimes, and sometimes not. But even if every time you run it on your personal computer, is seems like it's reading the variable properly, it's very likely that this same code will break on a different machine. So you are taking big risks.
I have a class with a getter getInt() and a setter setInt() on a certain field, say field
Integer Int;
of an object of a class, say SomeClass.
The setInt() here is synchronized-- getInt() isn't.
I am updating the value of Int from within multiple threads.
Each thread is getting the value Int, and setting it appropriately.
The threads aren't sharing any other resources in any way.
The code executed in each thread is as follows.
public void update(SomeClass c) {
while (<condition-1>) // the conditions here and the calculation of
// k below dont have anything to do
// with the members of c
if (<condition-2>) {
// calculate k here
synchronized (c) {
c.setInt(c.getInt()+k);
// System.out.println("in "+this.toString());
}
}
}
The run() method is just invoking the above method on the members updated from within the constructor by the params passed to it:
public void run() { update(c); }
When I run this on large sequences, the threads aren't interleaving much-- i see one thread executing for long without any other thread running in between.
There must be a better way of doing this.
I can't change the internals of SomeClass, or of the class invoking the threads.
How can this be done better?
TIA.
//=====================================
EDIT:
I'm not after manipulating the execution sequence of the threads. They all have the same priority. It`s just that what i see in the outcome is suggesting that the threads aren't sharing the execution time evenly-- one of them, once takes over, executing on. However, I can't see why this code should be doing this.
It`s just that what i see in the outcome is suggesting that the threads aren't sharing the execution time evenly
Well, this is exactly what you don't want if you are after efficiency. Yanking a thread from being executed and scheduling another thread is generally very costly. Therefore it's actually advantageous to do one of them, once takes over, executing on. Of course, when this is overdone you could see higher throughput but longer response time. In theory. In practice, JVMs thread scheduling is well tuned for almost all purposes, and you don't want to try changing it in almost all situations. As a rule of thumb, if you are interested in response times in millisecond order, you probably want to stay away messing with it.
tl;dr: It's not being inefficient, you probably want to leave it as it is.
EDIT:
Having said that, using an AtomicInteger may help in performance, and is in my opinion less error prone than using a lock (synchronized keyword). You need to be hitting that variable really very hard in order to get a measurable benefit though.
The JDK provides a nice solution for multi threaded int access, AtomicInteger:
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicInteger.html
As Enno Shioji has pointed out, letting one thread proceed might be the most efficient way to execute your code in some scenarios.
It depends on how much cost the thread synchronization imposes in relation to the other work of your code (which we don’t know). If you have a loop like:
while (<condition-1>)
if (<condition-2>) {
// calculate k here
synchronized (c) {
c.setInt(c.getInt()+k);
}
}
and the test for condition-1 and condition-2 and the calculation of k is rather cheap compared to the synchronization cost, the Hotspot optimizer might decide to reduce the overhead by transforming the code to something like this:
synchronized (c) {
while (<condition-1>)
if (<condition-2>) {
// calculate k here
c.setInt(c.getInt()+k);
}
}
(or a rather more complicated structure by performing loop unrolling and span the synchronized block over multiple iterations). The bottom line is that the optimized code might block other threads longer but let the one owning the lock finish faster resulting in an overall faster execution.
This does not mean that a single-threaded execution was the fastest way to handle your problem. It also doesn’t mean that using an AtomicInteger here would be the best option to solve the problem. It would create a higher CPU load and possibly a small acceleration but it doesn’t solve your real mistake:
It is completely unnecessary to update c within the loop at a high frequency. After all, your threads do not depend on seeing updates to c timely. It even looks like they are not using it at all. So the correct fix would be to move the update out of the loop:
int kTotal=0;
while (<condition-1>)
if (<condition-2>) {
// calculate k here
kTotal += k;
}
synchronized (c) {
c.setInt(c.getInt()+kTotal);
}
Now, all threads can run in parallel (assuming the code you haven’t posted here doesn’t contain inter-thread dependencies) and the synchronization cost is reduced to a minimum. You could still change it to an AtomicInteger as well but that’s not that important anymore.
Answering to this
i see one thread executing for long without any other thread running in between.
There must be a better way of doing this.
You can not control how threads will be executed. JVM does this for you, and does not like you to interfere in its work.
Still you can look at yield as your option, but that also does not ensure same thread will not be picked again.
The java.lang.Thread.yield() method causes the currently executing thread object to temporarily pause and allow other threads to execute.
I've found it better to use wait() and notify() than yield. Check out this example (seen from a book)-
class Q {
int n;
boolean valueSet = false;
synchronized int get() {
if(!valueSet)
wait(); //handle InterruptedException
//
valueSet = false;
notify();//if thread waiting in put, now notified
}
synchronized void put(int n) {
if(valueSet)
wait(); //handle InterruptedException
//
valueSet = true;
//if thread in get waiting then that is resumed now
notify();
}
}
or you could try using sleep() and join the threads in the end in main() but that isn't a foolproof way
You are having public void update(SomeClass c) method in your code and this method is an instance method in which you are passing the object as parameter.
synchronized(c) in your code is doing nothing. Let me show you with some example,
So if you will make different objects of this class and then try to make them different threads like,
class A extends Thread{
public void update(SomeClass c){}
public void run(){
update(c)
}
public static void main(String args[]){
A t1 = new A();
A t2 = new A();
t1.start();
t2.start();
}
}
Then both of these t1 & t2 will have their own copies of update method and the reference variable c which you are making synchronized will also be different for both the threads. t1 calls its own update() method and t2 calls its own update() method. So synchronization won't work.
Synchronization will work when you have something common for both the threads.
Something like,
class A extends Thread{
static SomeClass c;
public void update(){
synchronized(c){
}
}
public void run(){
update(c)
}
public static void main(String args[]){
A t1 = new A();
A t2 = new A();
t1.start();
t2.start();
}
}
This way the actual concept of synchronization will be applied.
I'm taking Java lessons. We're now into threads. It is the first time I'm experiencing multithreading so please excuse me if the question is very dumb :)
I've the following program:
public class Foo extends Thread {
private int x = 2;
public static void main(String[]args) {
new Foo().fun();
}
Foo () {
x = 5;
start();
}
public void fun() {
x = x - 1;
System.out.println(x);
}
public void run() {
x = x * 2;
}
}
When I run the program I get 4 as output. Will the output of the above program always be 4?
It will NOT always be 4.
If the Foo run() method executes before the main thread runs fun(), it will be 9.
If the Foo run() method executes whilst main is running fun(), it will be 8.
If main() completes before Foo starts, it will be 4
No, not always. Because in ctor you calling start() method, there's race condition between call to fun from main thread and run which will change value of x from Thread.start.
But, actually, without presence of proper synchronization there no guarantees on what output will be, irrelevant to the order in which fun and run will be called. Because synchronization ensures visibility of changes to threads, output can be 4 even if run will finish before fun gets called.
As you said you are learning multi-threading, you must know that you can never predict the sequence of execution of different threads.
This is a very simple program where the main thread will almost always finish first - but important thing to remember is you can never be sure in complex multi-threaded scenarios. In fact, you chose mult-threaded approach mostly in scenarios when one thread isn't dependent on execution of another.
btw try changing constructor this way:
Foo () {
x = 5;
start();
Thread.sleep(2 * 1000);
}
you may get different result.
Simon's answer is correct with a caveat. Java has some caching of variable values. If a variable is not set as volatile or if you don't use an atomic value, you may get the cached value instead of the most recent value.
yes it will always be 4. i see no reason for it not to be 4
you only run fun() and never run()
read java Thread man