Look at this code:
public class VolatileTest {
private static boolean ready = false;
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(){
#Override
public void run() {
ready = true;
System.out.println("t2 thread should stop!");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Thread t2 = new Thread(){
#Override
public void run() {
while(!ready){
System.out.println("invoking..");
}
System.out.println("I was finished");
}
};
t1.start();
t2.start();
}
}
I think the result of this code maybe:
t2 thread should stop!
invoking..
I was finished
because of in the multithreading, when the t1 modify 'ready' variable to true,then I made t1 sleep. At the moment, I think, to t2 the 'ready' variable is false!!! because t1 thread is not stop, the variable in t1 is invisible in t2.
But in fact.. I test many times. the result is always this:
Am my idea is wrong?
First of all, despite calling your class VolatileTest, you are not actually using volatile anywhere in your code.
Since the ready variable is not declared as volatile AND you are accessing it without any explicit synchronization, the behavior is not specified. Specifically, the JLS does not say whether the assignment made in thread 1 to the ready variable will be visible within thread 2.
Indeed, there is not even guaranteed that the run() method for thread 1 will be called before the run() method for thread 2.
Now it seems that your code (as written!) is behaving in a way that is consistent with the write of true always being visible immediately. However, there is no guarantee that that "always" is actually always, or that this will be the case on every Java platform.
I would not be surprised if the syscall associated with sleep is triggering memory cache flushing before the second thread is scheduled. That would be sufficient to cause consistent behavior. Moreover, there is likely to be serendipitous synchronization1 due to the println calls. However, these are not effects you should ever rely on.
1 - Somewhere in the output stream stack for System.out, the println call is likely to synchronize on the stream's shared data structures. Depending on the ordering of the events, this can have the effect of inserting a happens before relationship between the write and read events.
As I mentioned in my comment, there are no guarantees. ("There is no guarantee what value thread t2 will see for ready, because of improper synchronization in your code. It could be true, it could be false. In your case, t2 saw true. That is consistent with "there is no guarantee what value t2 will see")
You can easily get your test to fail by running it multiple times.
When I run below code that does your test 100 times, I always get 14-22 "notReadies", so 14-22% of the cases you will not see the change to ready in Thread t2.
public class NonVolatileTest {
private static boolean ready = false;
private static volatile int notReadies = 0;
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 100; i++) {
ready = false;
// Copy original Thread 1 code from the OP here
Thread t2 = new Thread() {
#Override
public void run() {
if (!ready) {
notReadies++;
}
while (!ready) {
System.out.println("invoking..");
}
System.out.println("I was finished");
}
};
t1.start();
t2.start();
// To reduce total test run time, reduce the sleep in t1 to a
// more suitable value like "100" instead of "5000".
t1.join();
t2.join();
}
System.out.println("Notreadies: " + notReadies);
}
}
Related
Imagine the following program.
class Main {
static class Whatever {
int x = 0;
}
public static void main(String[] args) {
Whatever whatever = new Whatever();
Thread t = new Thread(() -> {
whatever.x = 1;
});
t.start();
try {
t.join();
}
catch (InterruptedException e) {
}
System.out.println(whatever.x);
}
}
The main-thread has cached whatever and x is set to 0. The other thread starts, caches whatever and sets the cached x to 1.
The output is
1
so the main-thread has seen the write. Why is that?
Why was the write done to the shared cache and why has the main-thread invalidated its cache to read from the shared cache? Why don't I need volatile here?
Because of the main thread joining on it. See
17.4.5 in the JLS:
All actions in a thread happen-before any other thread successfully returns from a join() on that thread.
Btw it is true that not having a happens-before doesn’t necessarily mean something won’t be visible.
This question already has answers here:
synchronized block for an Integer object
(3 answers)
Closed 5 years ago.
Why doesn't variable named 'count' finally equal to 20000?
public class Main {
private Integer count = 0;
public void increment() {
synchronized (count) {
count++;
}
}
public static void main(String[] args) {
Main app = new Main();
app.doWork();
}
public void doWork() {
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
for (int i=0; i<10000; i++) {
increment();
}
}
});
Thread t2 = new Thread(new Runnable() {
#Override
public void run() {
for (int i=0; i<10000; i++) {
increment();
}
}
});
t1.start();
t2.start();
System.out.println(count);
}
It seems that thread loses the variable but when does it happen? The same happens in a case of using AtomicInteger too.
P.S. could you please recommend a good course with exercises for learning multithreading in Java?)
Because start creates a new thread, and when you print the count you aren't sure the thread execution is finished.
t1.start();
t2.start();
System.out.println(count); // Here you don't know if t1 and t2 ended their execution
Join threads to wait for them to complete the task:
t1.start();
t2.start();
t1.join(); // wait for t1 to finish
t2.join(); // wait for t2 to finish
System.out.println(count); // 20000
Note: You'll have to handle InterruptedException on join calls.
You synchronize on count. But your code changes count. Different threads synchronizing on different objects don't guarantee atomicity.
Use a separate final monitor object to synchronize on.
See also #BackSlash 's answer for making sure you print the correct end result.
Edit
His answer comes down to : if you print the result without waiting for the threads to finish on your main thread you'll see some intermediate result, or possibly even 0.
So you need to call join(), which blocks until the thread finishes, on both threads before printing the end result.
Here I have three simple classes:
Class 1:
public class ThreadSyncMain {
public static int count = 0; // volatile is not use
public static void main(String[] args) {
Thread thread1 = new Thread( new Thread1(),"Thread1" );
Thread thread2 = new Thread( new Thread2(),"Thread2");
thread1.start();
thread2.start();
}
}
Class 2:
public class Thread1 implements Runnable{
public void run() {
System.out.println("Thread1 Count :: "+ThreadSyncMain.count);
ThreadSyncMain.count++;
}
}
Class 3:
public class Thread2 implements Runnable{
public void run() {
System.out.println("Thread2 Count :: "+ThreadSyncMain.count);
}
}
The output is:
Thread1 Count :: 0
Thread2 Count :: 1
This means thread1 changed the value of count. So why change in thread1 affects in thread2 as I am not using any "volatile" keyword. Is "volatile" keyword not a matter in this scenario? How can I modify the code so as to test "volatile"?
Thanks in advance.
Update part:
I am updating the code after doing some hit and trial testing. Class 1 remains same. Here is the updated code:
Class 2: I added 100 millisecond delay.
public class Thread1 implements Runnable{
public void run() {
System.out.println("Thread1 Count :: "+ThreadSyncMain.count);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
ThreadSyncMain.count++;
}
}
Class 3: Added while loop. Inside it count is continuously monitored.
public class Thread2 implements Runnable{
public void run() {
while(true)
{
if(ThreadSyncMain.count == 1)
{
System.out.println("Thread2 Count :: "+ThreadSyncMain.count);
}
}
}
}
Now in this situation I have got the following outputs:
1. If "volatile" is not used in class1 output is:
Thread1 Count :: 0
2. If "volatile" is used in class1 output is:
Thread1 Count :: 0
Thread2 Count :: 1
Thread2 Count :: 1
Thread2 Count :: 1
.
.
.
Why volatile comes into picture in this scenario?
There's a memory view associated with each thread. These views are not guaranteed to be consistent between threads without the usage of locks. As such, sharing a variable as you've done above (without volatile) will work, since it's visible across threads, but can give you unreliable results. Using the volatile keyword means that the variable is consistently read between threads.
See here, and in particular note:
Volatile fields are special fields which are used for communicating
state between threads. Each read of a volatile will see the last write
to that volatile by any thread; in effect, they are designated by the
programmer as fields for which it is never acceptable to see a "stale"
value as a result of caching or reordering.
Volatile will guarantee the side effects from thread 1 become visible to thread 2. Without volatile, changes might, or might not, be visible.
Testing the effect of volatile is difficult, since it depends on low level aspects like hardware architecture, threading implementation, compiler optimization, and exact timing of even by the scheduler.
If I were to do so, I would write multithreaded tests that generate a high concurrency, and make sure I run on a multi-processor implementation. Then I might observe differences between code with and without volatile. The outcome of the tests would still be undeterministic.
It is possible the compiler isn't caching counter because it is a class wide variable. So the writes are in memory.
If you want to test volatile and non volatile write/reads..
public class VolatileExperiment
{
private int counter ;
private volatile int volatile_counter;
public void Counter()
{
new Thread( new Runnable(){
public void run()
{
++counter;
++volatile_counter;
//print
}
}).start();
new Thread( new Runnable(){
public void run()
{
++counter;
++volatile_counter;
//print
}
}).start();
//print counter
//print volatile
}
}
Using volatile ensures that compiler doesn't optimize code, so writes are done in memory and not in thread memory. So you should see volatile_counter updated.. while counter may not be affected
I'm learning how to work with threads in Java and I need some advice..
I want to print on the standard output numbers from 0..50 with the name of the thread that has done it using three threads.
I have two classes - class Counter that implements Runnable and class Main that creates and runs the threads. Counter has the variable c which is shared among the threads.
My idea was, that I increment c by 1 and then call yield() on the current thread so as the other threads would do the same. Repeat this until c reaches 50.
But it doesen't work, the numbers are printed out in wrong order. How do I fix this?
public class Counter implements Runnable {
Thread t1;
private int c = -1;
public Counter() {
}
public Counter(String name) {
t1 = new Thread(this, name);
t1.start();
}
#Override
public void run() {
while (c < 50) {
increment();
Thread.yield();
}
}
public void increment() {
if (c < 50) {
c++;
System.out.println(Thread.currentThread().getName() + ": " + c);
}
}
}
public class Main {
public static void main(String[] args) throws IllegalThreadStateException {
Counter c1 = new Counter();
Thread t1 = new Thread(c1, "Thread 1");
Thread t2 = new Thread(c1, "Thread 2");
Thread t3 = new Thread(c1, "Thread 3");
t1.start();
t2.start();
t3.start();
}
Edit: In the end I solved it this way. Thank you all who helped me with the tough start with multithreading.
import java.util.concurrent.atomic.AtomicInteger;
public class Counter2 implements Runnable {
// you could also use simple int
private AtomicInteger c = new AtomicInteger(-1);
private static final Object syncObject = new Object();
public Counter2() {
}
#Override
public void run() {
while (c.get() < 50) {
synchronized (syncObject) {
if (c.get() < 50) {
System.out.println(Thread.currentThread().getName() + ": " + c.incrementAndGet());
}
}
}
}
}
Use syncrhonized section in method increment with special static object.
private static final Object syncObj = new Object();
public void increment()
{
syncrhonized( syncObj )
{
c++;
System.out.println(c);
}
}
Or make this method synchronized via its declaration.
But it's wrong idea to store your real data in thread objects. Thread should just to manipulate with share objects but not to store them.\
And actually I don't understand why do you start thread in
Quoting from the javadoc Thread.yield(), emphasis by me:
public static void yield()
A hint to the scheduler that the
current thread is willing to yield its
current use of a processor. The
scheduler is free to ignore this
hint.
...
It is rarely appropriate to use
this method.
Make increment() synchronized in order to prevent other threads from entering the method concurrently.
In conjunction with yield() you should be able to get another thread print the next number (not always since the system might resume the thread that called yield again - see Ingo's answer - , but the order should still be the same).
synchronized increment() would mean that any thread that tries to enter that method on the same object would have to wait if another thread would have aquired the lock already by entering the method.
Yes your code won't work. Thread#yield() won't control the thread scheduler in the manner you desire. I"m curious what result you get. You'll probably get repeated numbers and some number that are slightly out of order.
You could use atomic integer which should remove all duplicates. But since the print statement is not atomic. You may still print your results out of order. So you should probably just synchronize the increment method. Also you don't really need yield so dump it.
If the purpose of the problem is to go from thread 1 to thread 2 to thread 3 back to thread 1, etc... Such that the results are
Thread 1:0
Thread 2:1
Thread 3:2
Thread 1:3
Thread 2:4
Thread 3:5
Thread 1:6
Thread 2:7
....
Then you'll need to lock the increment method and use wait and notifyAll. wait will cause other threads to halt processing until the current thread notifies them to start again.
I have been trying to solve a problem involving thread communication using wait() and notify(). Basically i have 2 threads T1 and T2 and i want them to be executed in the following order
T1 , T2, T1, T2 ..... How can i achieve that?
Actual Problem: There are 2 threads T1 - which prints odd numbers (say 1 - 100) and T2 - which prints even numbers (1 - 100). Now, the output should be 1, 2, 3, 4 , 5 , .... 100
You describe a Producer-Consumer pattern.
It's java implementations described in numerous java books including M.Grand "Patterns in Java. Volume I" and "Java 2: The Complete Reference" by Naughton and Schildt.
Basic idea: both threads should use 1 monitor (i.e. their code should be inside synchronized(monitor) {} blocks). You also need some flag variable which should indicate which of two threads should work at the moment.
When one of your threads is inside synchronized block it should check flag variable whether it's his turn to do the job. If yes, let it work and then change flag value and then notify all waiting threads. If no, then it should wait.
Look at the java.util.concurrent package, specifically the Exchanger
You're trying to parallelize a multistep process right? If so, see my answer here for an approach and some working code to do that. The answer involves an ExecutorService (or two) and one or more work queues.
For this approach, your processing needs to be able to fit into a Runnable, along with intermediate state information for the processing. You feed each step to the ExecutorService as a Runnable, which will add a second Runnable to perform the next step. This maintains the order of execution, but lets you effectively run as many threads as you wish in parallel.
:EDIT:
As another has suggested, the Exchanger library class can be used for this if you explicitly want to limit processing to 2 threads. I prefer the above approach because it maintains order of execution and allows you to use the modern 4-core (and 8-core) systems fully. It should also reduce synchronization a bit.
If T1 and T2 are 2 different implementations of the Runnable interface, with T1 being a thread that prints just odd numbers (1,3,...) and T2 being one that prints even number (1,2.....), this can be done by using the wait() and notify() methods on a shared monitor. The important thing is for each thread to check for a shared flag before printing its value. The below code works;
//The shared monitor
public class Mutex {
public static boolean oddFlag;
}
//The Thread that is supposed to print Odd numbers (assuming an upper limit of 99)
public class OddPrinter implements Runnable {
private Mutex mutex;
public OddPrinter(Mutex mutex) {
this.mutex = mutex;
}
public synchronized void run() {
System.out.println("Started Thread: OddPrinter");
int i;
for(i=1; i<100; i+=2 ) {
synchronized (mutex) {
while(!Mutex.oddFlag) {
try {
mutex.wait();
} catch (InterruptedException ie) {
Thread.currentThread().interrupted();
}
}
if(Mutex.oddFlag == true) {
System.out.println("Print from OddPrinter: "+i);
Mutex.oddFlag = false;
mutex.notify();
}
}
}
System.out.println("Finished Thread: OddPrinter: "+i);
}
}
//The Thread that is supposed to print Odd numbers (assuming an upper limit of 98)
public class EvenPrinter implements Runnable {
private Mutex mutex;
public EvenPrinter(Mutex mutex) {
this.mutex = mutex;
}
public synchronized void run() {
System.out.println("Started Thread: EvenPrinter");
int i;
for(i=2; i<100; i+=2) {
synchronized (mutex) {
while(Mutex.oddFlag) {
try {
mutex.wait();
} catch (InterruptedException ie) {
Thread.currentThread().interrupted();
}
}
if(!(Mutex.oddFlag == true)) {
System.out.println("Print from EvenPrinter: "+i);
Mutex.oddFlag = true;
mutex.notify();
}
}
}
System.out.println("Finished Thread: EvenPrinter: "+i);
}
}
//The test harness that executes the threads
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class NumberPrinterTest {
public static void main(String[] args) throws Exception{
ExecutorService es = Executors.newFixedThreadPool(2);
Mutex mutex = new Mutex();
OddPrinter op = new OddPrinter(mutex);
EvenPrinter ep = new EvenPrinter(mutex);
Mutex.oddFlag = true;
es.execute(op);
es.execute(ep);
if(null != es){
es.shutdown();
try {
es.awaitTermination(1, TimeUnit.MINUTES);
} catch (InterruptedException e) {
Thread.currentThread().interrupted();
}
}
}
}