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.
Related
I'm new at Concurrency, i'm trying to understand synchronized block:
public static int count1 = 0;
public static Object lock1 = new Object();
public static void add(){
synchronized (lock1) {
count1++;
}
}
my problem is with lock1, it doesn't work, when the method starts printing the color, it prints them randomly, so i think the problem is in synchronized block, because i watch some tutorials about this, all of them say the lock object must be static so no interference happens, but here i don't see that, Why?
This is the method that prints the color of each thread:
public static void compute(){
String color = null;
switch (Thread.currentThread().getName()) {
case "First Count Down":
color = TextColors.ANSI_YELLOW;
break;
case "Second Count Down":
color = TextColors.ANSI_MAGENTA;
break;
}
for (int i=0;i<100;i++) {
System.out.println(color + Thread.currentThread().getName() + "is Running");
//add();
add();
}
}
and this is the threads :
public static void main(String[] args) {
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
compute();
}
});
t1.setName("First Count Down");
Thread t2 = new Thread(new Runnable() {
#Override
public void run() {
compute();
}
});
t2.setName("Second Count Down");
t1.start();
t2.start();
try{
t1.join();
t2.join();
}catch (InterruptedException io){
io.printStackTrace();
}
System.out.println("Count1 = " + count1 + " Count2 = " + count2);
}
Sorry if my English is bad, i'm not a native speaker, thanks in advance
First of all, I think now I understand your question. You're trying to print out your lines without interfering with the lines of the other threads.
To achieve this, you have to "protect" the part of your code, which prints out one line, not to get printed out another line at the same time from another thread.
The protection can be done by synchronizing those lines of code.
You are currently synchronizing only the addition to that counter.
Your lock (the object you're locking on, the one and only instance of that new Object()) is static and you do not change it in your code, so it must work.
public static Object lock1 = new Object();
You could make the variable to final to get immutable, but currently that's not the problem. I would recommend that though.
The lock means, that if any other thread is landing in (executing) the same line of code (the beginning of the synchronized block), they won't get execution until the blocking thread is giving up its lock. This is only true, if they holding and asking for the very same lock. And as you're only using the very same new Object() instance, your lock should be okay.
Currently your code is built up that the add() method basically waits until one of the threads is counting up one.
If you want to change it so that you're getting separately printed out lines, try to synchronize the "line printing block" like this:
synchronized (lock1) {
System.out.println(color + Thread.currentThread().getName() + "is Running");
add();
}
And let the counting not be synchronized.
private static void add(){
count1++;
}
This would work but mostly you don't want to let your add() method unsynchronized. It could be executed from other threads, who knows. But for your case, those changes would help.
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.
I am working on a codebase that implements something similar to this. We are having issues with one of the threads failing to synchronize with other threads when the value of count is incremented, thus going into an infinite loop.
The problem seems to come from the non-atomic behaviour of the post-increment operator.
You can find the code Repl here NB: You may need to run the code at least 3 times to observe it.
I need support to implement increment of count by as many threads as possible in a thread safety way.
class Main {
static volatile Integer count = new Integer(0); //boxed integer is intentional to demonstrate mutable instance
static final void Log(Object o) {
System.out.println(o);
}
static synchronized void increaseCount(){
count++;
}
static synchronized Integer getCount(){
return count;
}
public static void main(String[] arg) throws InterruptedException {
new Thread(() -> {
while (getCount() != 60) {
increaseCount();
Log(count +" thread A");
}
}).start();
new Thread(() -> {
while (getCount() != 20) {
increaseCount();
Log(count +" thread B");
}
}).start();
new Thread(() -> {
while (getCount() != 50) {
increaseCount();
Log(count+" thread C");
}
}).start();
}
}
If many threads are incrementing a shared counter, there is no guarantee about which thread will see a particular value of the counter. To make sure a particular thread sees a particular value, that thread has to see every value of the counter. And then you might as well just have one thread, because they are all working in lockstep with each other.
If you want to do some work for every value of the counter, with special handling for particular values, and you want to parallelize that workload, every thread needs to be prepared to perform the special handling. Here's an example of how you could do that:
class Main {
private static class Worker implements Runnable {
private final AtomicInteger counter;
private final Set<Integer> triggers;
Worker(AtomicInteger counter, Set<Integer> triggers) {
this.counter = counter;
this.triggers = triggers;
}
public void run() {
String name = Thread.currentThread().getName();
while (!triggers.isEmpty()) {
int value = counter.getAndIncrement();
try { /* Simulate actually doing some work by sleeping a bit. */
long delay = (long) (-100 * Math.log(1 - ThreadLocalRandom.current().nextDouble()));
TimeUnit.MILLISECONDS.sleep(delay);
} catch (InterruptedException ex) {
break;
}
boolean triggered = triggers.remove(value);
if (triggered) {
System.out.println(name + " handled " + value);
} else {
System.out.println(name + " skipped " + value);
}
}
}
}
public static void main(String[] arg) throws InterruptedException {
AtomicInteger counter = new AtomicInteger();
Set<Integer> triggers = new ConcurrentSkipListSet<>();
triggers.add(60);
triggers.add(20);
triggers.add(50);
int concurrency = 4;
ExecutorService workers = Executors.newFixedThreadPool(concurrency);
for (int i = 0; i < concurrency; ++i) {
workers.execute(new Worker(counter, triggers));
}
workers.shutdown();
}
}
The number of worker threads can be adjusted so that it makes sense given the number of cores on your machine, and the real workload (how CPU or I/O intensive the tasks are).
In this approach, each value of the counter is processed by just one thread, and it doesn't matter which thread gets a "sentinel" value. But, when all the sentinel values have been processed, all the threads shut down. Threads coordinate with each other through the counter, and the set of "triggers", or sentinel values that they need to handle.
This question already has answers here:
Thread won't stop when I want it to? (Java)
(2 answers)
Loop doesn't see value changed by other thread without a print statement
(1 answer)
Closed 4 years ago.
I have tested something about multithreading. I find the snippet lasts much more than 3 seconds, and is not printing the last System.out.println("program end");. Why?
public class hello {
static Boolean flag = false;
public static void main(String args[]) throws InterruptedException {
MyThread t = new MyThread();
t.start();
Thread.sleep(3000);
hello.flag = true;
}
static class MyThread extends Thread {
public void run(){
System.out.println("Thread start");
while(true){
if(hello.flag){
break;
}
}
System.out.println("Thread end");//why not print this statement? but run in debug mode, it will print this statement correctly
}
}
}
program run result as follow:
Different threads use different memory space caches each.
It means the first thread has the variable in its own cache, and the other thread has the variable in its own cache. Thus each thread seeing the same variable in different states.
In the absence of appropriate synchronization mechanisms between the two thread, they have no reason to try and reconcile the difference in their caches. It would severely deter performances to do that without being instructed to.
One very easy synchronization mechanism you could have here, would be to make variable flag, volatile. That will make the threads synchronize their caches on this variable on each read/write.
Use volatile with flag to make thread read actual value of flag not from its local cache..
public class hello {
//make flag volatile
volatile static Boolean flag = false;
public static void main(String args[]) throws InterruptedException {
MyThread t = new MyThread();
t.start();
Thread.sleep(3000);
hello.flag = true;
}
static class MyThread extends Thread {
public void run(){
System.out.println("Thread start");
while(true){
if(hello.flag){
break;
}
}
System.out.println("Thread end");//why not print this statement? but run in debug mode, it will print this statement correctly
}
}
}
Please go through below link to see how it works..
https://docs.oracle.com/cd/E19683-01/806-5222/codingpractices-1/index.html
I'm trying to illustrate the use and importance of volatile with an example that would really not give a good result if volatile was omitted.
But I'm not really used to using volatile. The idea of the following code is to cause an infinite loop if volatile is omitted, and be perfectly thread-safe if volatile is present. Is the following code thread-safe? Do you have any other realistic and short example of code that uses volatile and would give an obviously incorrect result without it?
Here's the code:
public class VolatileTest implements Runnable {
private int count;
private volatile boolean stopped;
#Override
public void run() {
while (!stopped) {
count++;
}
System.out.println("Count 1 = " + count);
}
public void stopCounting() {
stopped = true;
}
public int getCount() {
if (!stopped) {
throw new IllegalStateException("not stopped yet.");
}
return count;
}
public static void main(String[] args) throws InterruptedException {
VolatileTest vt = new VolatileTest();
Thread t = new Thread(vt);
t.start();
Thread.sleep(1000L);
vt.stopCounting();
System.out.println("Count 2 = " + vt.getCount());
}
}
Victor is right, there are issues with your code: atomicity and visibility.
Here's my edition:
private int count;
private volatile boolean stop;
private volatile boolean stopped;
#Override
public void run() {
while (!stop) {
count++; // the work
}
stopped = true;
System.out.println("Count 1 = " + count);
}
public void stopCounting() {
stop = true;
while(!stopped)
; //busy wait; ok in this example
}
public int getCount() {
if (!stopped) {
throw new IllegalStateException("not stopped yet.");
}
return count;
}
}
If a thread observes that stopped==true, it's guaranteed that the work completes and the result is visible.
There is a happens-before relation from volatile write to volatile read (on the same variable), so if there are two threads
thread 1 thread 2
action A
|
volatile write
\
volatile read
|
action B
action A happens-before action B; writes in A are visible by B.
It was always hard to me to illustrate concurrency problems in a convincing way: well, fine, it's all nice about happens-before and stuff, but why should one care? Is there a real problem? There are lots and lots of poorly written, poorly synchronized programs—and they still work most of the time.
I used to find a resort in a "works most of the time VS works" rhetoric—but, frankly, it's a weak approach. So what I needed is an example which would make difference obvious—and, preferably, painful.
So here is a version which actually does show the difference:
public class VolatileExample implements Runnable {
public static boolean flag = true; // do not try this at home
public void run() {
long i = 0;
while (flag) {
if (i++ % 10000000000L == 0)
System.out.println("Waiting " + System.currentTimeMillis());
}
}
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(new VolatileExample());
thread.start();
Thread.sleep(10000L);
flag = false;
long start = System.currentTimeMillis();
System.out.println("stopping " + start);
thread.join();
long end = System.currentTimeMillis();
System.out.println("stopped " + end);
System.out.println("Delay: " + ((end - start) / 1000L));
}
}
A simple run shows:
Waiting 1319229217263
stopping 1319229227263
Waiting 1319229242728
stopped 1319229242728
Delay: 15
That is, it takes more than ten seconds (15 here) for a running thread to notice there was any change.
With volatile, you have:
Waiting 1319229288280
stopping 1319229298281
stopped 1319229298281
Delay: 0
that is, exiting (almost) immediately. The resolution of currentTimeMillis is around 10ms, so the difference is more that 1000 times.
Note it was Apple's version of (ex-)Sun JDK, with -server option. The 10-second wait was added in order to let JIT compiler find out that the loop is hot enough, and optimize it.
Hope that helps.
Simplifying #Elf example further, where the other thread will never get the value which was updated by other thread. Removing System.out.println as there is synchronized code inside println and out is static, somehow that helps the other thread to get the latest value of flag variable.
public class VolatileExample implements Runnable {
public static boolean flag = true;
public void run() {
while (flag);
}
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(new VolatileExample());
thread.start();
Thread.sleep(1000L);
flag = false;
thread.join();
}
}
To illustrate the importance of the volatile keyword when it comes to concurrency, all you need to do is make sure that the volatile field is modified and read in a separate threads.
UPDATE My answer is wrong, see answer from irreputable.
It's not thread-safe, since access to count is not there's only one writer thread. Should there be another writer thread, value of count would be become inconsistent to the number of updates.
Visibility of count value to main thread is ensured by checking stopped volatile inside getCount method. This is what is called piggybacking on synchronization in Concurrency in practice book.
Wrong code with which we cannot assume x = 1 also if y is already 2:
Class Reordering {
int x = 0, y = 0;
public void writer() {
x = 1;
y = 2;
}
public void reader() {
int r1 = y;
int r2 = x;
}
}
Example of use of volatile keyword:
class VolatileExample {
int x = 0;
volatile boolean v = false;
public void writer() {
x = 42;
v = true;
}
public void reader() {
if (v == true) {
//uses x - guaranteed to see 42.
}
}
}
Source: http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html