This question already has answers here:
Why is this code working without volatile?
(2 answers)
Closed 2 years ago.
I'm playing with volatile keyword in Java and I have this code that tries to show that a thread doesn't see changes introduced by another thread unless we declare data as volatile. I was expecting that the code below will never terminate as I haven't declared the shared data as volatile. Any ideas why this code actually terminates?
public class VolatileTest {
public static void main(String[] args) throws InterruptedException {
var holder = new Holder();
new Thread(() -> {
try {
Thread.sleep(500);
} catch (InterruptedException e) { }
for(int i = 0; i<100000; i++) {
holder.counter++;
}
}).start();
var t = new Thread(() -> {
while(holder.counter < 10000) {
System.out.println("Jestem w pętli");
try {
Thread.sleep(400);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t.start();
t.join();
}
static class Holder {
int counter = 0;
}
}
Thread 1 MAY not see change from the Thread 2 immediately if you don't use volatile, but eventually once in the future, that will happen when Thread 2 empty CPU cache to main memory. In your example, if you use volatile on counter field, writing thread will always write to main memory when you call holder.counter++ and reading thread will read from main memory every time you call holder.counter < 10000.
Related
This question already has answers here:
What's the difference between Thread start() and Runnable run()
(14 answers)
Closed 6 months ago.
I am new to Java, I have want to starts 02 thread to increase an attribute of an object and I want to print out the value of this attribute until it reach a certain value.
I use 02 threads started inside increaseByThread() method.
I use two code snippets as follows but they behave differently.
The first one I use while loop in the main thread to check for the value change but it only print out the last value after two sub-threads finish running and return 40.
The second one I use while loop but inside another sub-thread for checking value and it prints out every value, it means that 03 sub-threads are running in parallel (please see the second snippet below)
My question is that why in the first snippet, the while loop block only called after test.increaseByThread() finish execution?
public class ThreadIncrease {
public volatile int[] count={0};
public void increaseByThread(){
Runnable first= () -> {
for(int i=0;i<20;i++) {
count[0] = count[0] + 1;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// System.out.println(count[0]);
}
};
Runnable second= () -> {
for(int i=0;i<20;i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
count[0] = count[0] + 1;
// System.out.println(count[0]);
}
};
Thread firstThread=new Thread(first);
Thread secondThread=new Thread(second);
firstThread.run();
secondThread.run();
}
public static void main(String[] args) {
ThreadIncrease test=new ThreadIncrease();
Runnable check=()->{
while(true){
System.out.println(test.count[0]);
if(test.count[0]<10){
System.out.println("count is: "+test.count[0]);
}
else{
System.out.println("Break");
break;
}
}
};
// Thread checkThread=new Thread(check);
// checkThread.start();
test.increaseByThread();
while(true){
System.out.println(test.count[0]);
if(test.count[0]<10){
System.out.println("count is: "+test.count[0]);
}
else{
System.out.println("Break");
break;
}
}
}
}
The second one I use while loop but inside another sub-thread for checking value and it prints out every value, it means that 03 sub-threads are running in parallel:
public class ThreadIncrease {
public volatile int[] count={0};
public void increaseByThread(){
Runnable first= () -> {
for(int i=0;i<20;i++) {
count[0] = count[0] + 1;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// System.out.println(count[0]);
}
};
Runnable second= () -> {
for(int i=0;i<20;i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
count[0] = count[0] + 1;
// System.out.println(count[0]);
}
};
Thread firstThread=new Thread(first);
Thread secondThread=new Thread(second);
firstThread.run();
secondThread.run();
}
public static void main(String[] args) {
ThreadIncrease test=new ThreadIncrease();
Runnable check=()->{
while(true){
System.out.println(test.count[0]);
if(test.count[0]<10){
System.out.println("count is: "+test.count[0]);
}
else{
System.out.println("Break");
break;
}
}
};
Thread checkThread=new Thread(check);
checkThread.start();
test.increaseByThread();
// while(true){
// System.out.println(test.count[0]);
// if(test.count[0]<10){
// System.out.println("count is: "+test.count[0]);
// }
// else{
// System.out.println("Break");
// break;
// }
// }
}
}
You have not started any new thread yet.
Each thread needs to run something. That is it's run method. But by invoking thread.run you just execute that code on the calling thread, which is your main thread.
Instead you need to start the new thread using thread.start(). This function will return immediately, and the newly created thread will execute run() in parallel.
Since you were running everything on the main thread the perception is right that the main thread was blocked until all the runs finished.
Thread.run(), which you are calling in increaseByThread() runs the Thread's Runnable in the current thread. I think you have confused it with Thread.start(), which starts a new thread to run the Runnable.
See What's the difference between Thread start() and Runnable run() and When would you call java's thread.run() instead of thread.start()?
I'm looking at other examples here and in other sites and I'm not understanding what I'm doing wrong. I'm trying to do a program that one thread sets the value of an object to the values 1 to 10, but I want to wait for it to change the value until other thread reads it, so I can print them and have a list from 1 to 10.
My readThread run method just loops from 1 to 10 calling the following method:
private synchronized int receive() {
try {
wait();
int value = this.mainThread.getValor();
notify();
return value;
} catch (InterruptedException e) {
e.printStackTrace();
}
return -1;
}
My writeThread run method just loops from 1 to 10 calling the following method:
private synchronized void send(int n) {
try {
this.mainThread.setValor(n);
notify();
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
The main method is the following:
public static void main(String[] args) {
MainThread mt = new MainThread();
ReadThread rt = new ReadThread(mt);
WriteThread wt = new WriteThread(mt);
wt.start();
rt.start();
}
The class MainThead has the property "valor" defined with its getter and setter
Thank you for your help
There are a couple of obvious problems.
It looks as if you are synchronising on the same lock (there isn't enough code to be 100% sure). Generally you should create an object specifically to use as a lock.
send may be executed before receive. In that case the first notify will do nothing, and both threads will stall in wait.
In theory, there is no guarantee that wait will not wakeup spontaneously. For this and other reasons, you really want the wait inside a while loop.
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 am now reading 《effective Java》 and meeting a confusion.
For code 1 (java8) :
public class StopThreadTest {
private static Boolean stopRequest = false;
public static void main(String[] args) throws InterruptedException {
new Thread(()->{
int i = 0;
while (!stopRequest) {
i++;
//System.out.println("i: " + i);
}
}).start();
TimeUnit.SECONDS.sleep(1);
stopRequest = true;
}
}
the program never terminates.
For code 2(java8):
public class StopThreadTest {
private static Boolean stopRequest = false;
public static void main(String[] args) throws InterruptedException {
new Thread(()->{
int i = 0;
while (!stopRequest) {
i++;
System.out.println("i: " + i);
}
}).start();
TimeUnit.SECONDS.sleep(1);
stopRequest = true;
}
}
Just adding System.out.println(), the program run about 1 second.
Can anybody tell me why?
System.out.println() is synchronized, removing the visibility issues with the original code. Without it, the thread can use its cached value of stopRequest and keep on running, but when println() is involved, caches are flushed and the modified value can be seen.
From PrintStream.println(String x)
synchronized (this) {
print(x);
newLine();
}
Note that this is a side-effect only. It explains the difference in behaviour, but it's not something you can rely on for correct functionality of code.
I want to write two Threads that increment a number and decrement a number, and a main Thread that determines when the two numbers are equal. For example, one number starts at 0 and the other number starts at 10... When they are both 5, the main Thread should recognize they are equal and print "They meet!".
In this code, the main Thread can't not compare numup and numdown successfully:
public class Number implements Runnable {
public static int numup = 0;
public static int numdown = 10;
public Number() {
}
public static void main(String args[]) {
Number number = new Number();
Thread T1 = new Thread(number, "up");
Thread T2 = new Thread(number, "down");
T1.start();
T2.start();
while (true) {
if (numup == 5 && numdown == 5) {
System.out.println("Meet!");
System.exit(0);
}
}
}
public void run() {
while (true) {
if (Thread.currentThread().getName().equals("up")) {
numup++;
System.out.println(numup);
} else if (Thread.currentThread().getName().equals("down")) {
numdown--;
System.out.println(numdown);
}
try {
Thread.sleep(1000);
} catch (Exception e) {
System.out.println("wake!");
}
}
}
}
The failed result:
1
9
8
2
7
3
6
4
5
5
6
4
7
3
8
2
1
9
However, when I make the main Thread sleep a few milliseconds, it works:
public class Number implements Runnable {
public static int numup = 0;
public static int numdown = 10;
public Number() {
}
public static void main(String args[]) {
Number number = new Number();
Thread T1 = new Thread(number, "up");
Thread T2 = new Thread(number, "down");
T1.start();
T2.start();
while (true) {
try {
Thread.sleep(10);
} catch (Exception e) {
System.out.println(Thread.currentThread().getName() + "was waked!");
}
if (numup == 5 && numdown == 5) {
System.out.println("They Meet!");
System.exit(0);
}
}
}
public void run() {
while (true) {
if (Thread.currentThread().getName().equals("up")) {
numup++;
System.out.println(numup);
} else if (Thread.currentThread().getName().equals("down")) {
numdown--;
System.out.println(numdown);
}
try {
Thread.sleep(1000);
} catch (Exception e) {
System.out.println("wake!");
}
}
}
}
The successful result:
1
9
2
8
3
7
4
6
5
5
They Meet!
Why does the added delay make it work?
This could be because of the CPU cache. When the number thread updates the value of the variable (this goes from its CPU cache to main memory) by then the CPU cache of the corresponding main thread might not have got updated.
So when main thread check's the value of the variable it was still the old value.
You can use Volatile. OR
Use AtomicInteger for these operations.
You can refer to this link.
In a multithreaded application where the threads operate on non-volatile variables, each thread may copy variables from main memory into a CPU cache while working on them, for performance reasons. If your computer contains more than one CPU, each thread may run on a different CPU. That means, that each thread may copy the variables into the CPU cache of different CPUs.
With non-volatile variables there are no guarantees about when the Java Virtual Machine (JVM) reads data from main memory into CPU caches, or writes data from CPU caches to main memory.
Volatile:
public static volatile int numup = 0;
public static volatile int numdown = 10;
Atomic Integer:
import java.util.concurrent.atomic.AtomicInteger;
public class Number implements Runnable {
public static AtomicInteger numup = new AtomicInteger(0);
public static AtomicInteger numdown = new AtomicInteger(10);
public Number() {
}
public static void main(String args[]) {
Number number = new Number();
Thread T1 = new Thread(number, "up");
Thread T2 = new Thread(number, "down");
T1.start();
T2.start();
while (true) {
if (numup.get() == 5 && numdown.get() == 5) {
System.out.println("Meet!");
System.exit(0);
}
}
}
public void run() {
while (true) {
if (Thread.currentThread().getName().equals("up")) {
numup.incrementAndGet();
System.out.println(numup);
} else if (Thread.currentThread().getName().equals("down")) {
numdown.decrementAndGet();
System.out.println(numdown);
}
try {
Thread.sleep(1000);
} catch (Exception e) {
System.out.println("wake!");
}
}
}
}
Quick answer - add volatile modifier to numdown and numup.
Long answer:
Your problem is that other thread can't see that numdown and numup has changed because of couple of reasons:
JVM may optimize and reorder the execution order of bytecode instructions.
Modern processors also do instruction reordering.
The value is cached in processor's cache line (L1, L2, L3 cache level).
So, when you introduce a volatile variable it is guaranteed by java that writes from one thread will have happen-before relationships with reads form another thus making changes visible to the another thread. On more low-level it could introduce a memory barrier
Anyway, it would not fit into the SO answer to explain properly how it's works, but there is a number of excellent resources you could read/watch if you're interested to dive deeper into the topic.
https://zeroturnaround.com/rebellabs/java-memory-model-pragmatics-by-aleksey-shipilev/
Do you ever use the volatile keyword in Java?
http://mechanical-sympathy.blogspot.com/2011/07/memory-barriersfences.html
Cheers!
Interesting one and a good answer given by Yegor. Just to add my observation that the program halts even if you write the if (numup == 5 && numdown == 5) check inside the while loop of the run() method.
In case you want to try out with the volatile keyword.
public static volatile int numup = 0;
public static volatile int numdown = 10;
volatile keyword will ensure that your threads won't cache the value of the variable and will always retrieve it from the main memory.
import java.io.IOException;
public class Test implements Runnable {
private int m, n;
public synchronized void run() {
try {
for (int i = 0; i < 10; i++) {
m++;
n++;
Thread.sleep(100);
System.out.println(m + ", " + n);
}
} catch (InterruptedException e) {
}
}
public static void main(String[] args) {
try {
Test a = new Test();
new Thread(a).start();
new Thread(a).start();
} catch (Exception e) {
}
}
}
You are correct that you cannot start the same thread twice. But you aren't doing that here. You are starting two separate threads once each.
Your code is essentially the same as:
Thread t1 = new Thread(a);
t1.start();
Thread t2 = new Thread(a);
t2.start();
You are declaring 2 different threads and running them one after another. If you add the following code.
public synchronized void run() {
System.out.println("thread started");
try {
for (int i = 0; i < 10; i++) {
m++;
n++;
Thread.sleep(100);
System.out.println(m + ", " + n);
}
} catch (InterruptedException e) {
}
System.out.println("thread fininshed");
}
You can easily see where the first thread ends and then the second thread starts.
Each of your threads needs to execute task described in instance of Test class. More precisely in its run method. In your case both threads will need to execute task of Test but they will also need to use same instance of this class (which is stored in a reference).
Problem is that run method is synchronized which means it uses monitor/lock of current instance (this - available via a reference) which means that both threads can't execute it at the same time. To be more precise one of threads will need to wait until other thread will finish execution code from that synchronized block (which is entire body of run).
So in your case
one of your threads will print
enter synchronized block locked on a
print values in range 1-10
exit synchronized block locked on a
so now another thread can
enter synchronized block locked on a
print values in range 11-20 (since m and n will be increased each time in loop)
exit synchronized block locked on a