Multithreading "unpredictable" behavior [duplicate] - java

This question already has answers here:
Relationship between Threads and println() statements
(2 answers)
Closed 6 years ago.
I was going through the use cases for volatile and I have encountered the below scenario:
private static boolean stop = false;
public static void main(String[] args) throws InterruptedException {
Thread runner = new Thread(new Runnable() {
#Override
public void run() {
int i = 0;
long start = System.currentTimeMillis();
while(!stop){
i++;
}
System.out.println("I m done after "+(System.currentTimeMillis() - start));
}
});
runner.start();
Thread.sleep(2000);
stop = true;
}
The above code runs indefinitely. Which is fine due to hoisting done by the compiler in an attempt to optimize the code. However, if I replace, i++ with some other statement e.g. System.out.println("Hello"). It stops after 2 seconds.
Why the behavior is like this? I am using jdk1.7.0_51.
Note:
I know I should declare stop as volatile. However, I would like to know the reason for the behavior in the above case.

The standard output is a shared resource across threads. Java's PrintStream class is made thread-safe using synchronized blocks, and all synchronized blocks are memory barriers in java, that's why changes on the stop field become visible inside the loop. However, you shouldn't rely on this.
For example, take a look at the PrintStream.println implementation:
public void println(String paramString)
{
synchronized (this)
{
print(paramString);
newLine();
}
}

Related

synchronized keyword not making the function synchronized: Java [duplicate]

This question already has answers here:
What does 'synchronized' mean?
(17 answers)
Closed 1 year ago.
I was practicing multithreading in java and wrote the below code
class Printer {
synchronized void printHi(String x) {
System.out.println(x);
}
}
class MyThread extends Thread {
Printer objm;
MyThread(Printer a) {
objm = a;
}
#Override
public void run() {
for (int i = 0; i < 10; i++) {
objm.printHi("MyThread" + i);
}
}
}
class YourThread extends Thread {
Printer objy;
YourThread(Printer a) {
objy = a;
}
#Override
public void run() {
for (int i = 0; i < 10; i++) {
objy.printHi("YourThread" + i);
}
}
}
public class test {
public static void main(String[] args) {
Printer ob = new Printer();
MyThread mt = new MyThread(ob);
YourThread yt = new YourThread(ob);
mt.start();
yt.start();
}
}
Sometimes I gets the output as:
MyThread0
YourThread0
MyThread1
YourThread1
MyThread2
YourThread2
MyThread3
YourThread3
YourThread4
MyThread4
MyThread5
MyThread6
YourThread5
MyThread7
YourThread6
MyThread8
MyThread9
YourThread7
YourThread8
YourThread9
Which is asynchronous. Why is it so even after making the function printHi() as synchronized?
Synchronized means only one thread can be running a block of code marked synchronized on the same lock object (instance of the object for the case of a synchronized method). It does not mean threads will run in order. It is perfectly correct for the two threads to enter those synchronized blocks in any order, and any number of times before the next thread does. What you want is much more difficult and beyond what a simple synchronized block can do.
If you want it to always go Thread A, Thread B, Thread A, Thread B- first I'd question that those two things should actually be separate threads. Wanting things to run sequentially like that is the number one sign you aren't asynchronous and shouldn't be multiple threads. But if they do, you're probably best off with two threads with message handlers, sending messages to each other about when they're allowed to run. Or using semaphores to signal each other. It's hard to give exact advice because the problem here is obviously a trivialized version of something harder, and without the details the right implementation is hard to guess.
You're synchronizing the printHi function call. That means two instances of printHi on the same object won't run at the same time. That's great. It means you'll never get output like
MyThYourThreadread77
(Side note: Java's printing primitives are already somewhat synchronized if I recall correctly, so that shouldn't happen anyway. But for demonstrative purposes, it'll do)
However, your loop is not synchronized. If you want the whole loop to only happen in one thread at a time, remove synchronized from print and write your loop as
synchronized (objm) {
for (int i = 0; i < 10; i++) {
objm.printHi("MyThread" + i);
}
}
(and the same for objy in YourThread)
There's still no guarantee on which one will happen first, but the two loops won't interrupt each other in this case.

Java Thread seemingly skipping conditional statement [duplicate]

This question already has answers here:
Why doesnt this Java loop in a thread work?
(4 answers)
Closed 3 years ago.
For a recent library I'm writing, I wrote a thread which loops indefinitely. In this loop, I start with a conditional statement checking a property on the threaded object. However it seems that whatever initial value the property has, will be what it returns even after being updated.
Unless I do some kind of interruption such as Thread.sleep or a print statement.
I'm not really sure how to ask the question unfortunately. Otherwise I would be looking in the Java documentation. I have boiled down the code to a minimal example that explains the problem in simple terms.
public class App {
public static void main(String[] args) {
App app = new App();
}
class Test implements Runnable {
public boolean flag = false;
public void run() {
while(true) {
// try {
// Thread.sleep(1);
// } catch (InterruptedException e) {}
if (this.flag) {
System.out.println("True");
}
}
}
}
public App() {
Test t = new Test();
Thread thread = new Thread(t);
System.out.println("Starting thread");
thread.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {}
t.flag = true;
System.out.println("New flag value: " + t.flag);
}
}
Now, I would presume that after we change the value of the flag property on the running thread, we would immediately see the masses of 'True' spitting out to the terminal. However, we don't..
If I un-comment the Thread.sleep lines inside the thread loop, the program works as expected and we see the many lines of 'True' being printed after we change the value in the App object. As an addition, any print method in place of the Thread.sleep also works, but some simple assignment code does not. I assume this is because it is pulled out as un-used code at compile time.
So, my question is really: Why do I have to use some kind of interruption to get the thread to check conditions correctly?
So, my question is really: Why do I have to use some kind of interruption to get the thread to check conditions correctly?
Well you don't have to. There are at least two ways to implement this particular example without using "interruption".
If you declare flag to be volatile, then it will work.
It will also work if you declare flag to be private, write synchronized getter and setter methods, and use those for all accesses.
public class App {
public static void main(String[] args) {
App app = new App();
}
class Test implements Runnable {
private boolean flag = false;
public synchronized boolean getFlag() {
return this.flag;
}
public synchronized void setFlag(boolean flag) {
return this.flag = flag;
}
public void run() {
while(true) {
if (this.getFlag()) { // Must use the getter here too!
System.out.println("True");
}
}
}
}
public App() {
Test t = new Test();
Thread thread = new Thread(t);
System.out.println("Starting thread");
thread.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {}
t.setFlag(true);
System.out.println("New flag value: " + t.getFlag());
}
But why do you need to do this?
Because unless you use either a volatile or synchronized (and you use synchronized correctly) then one thread is not guaranteed to see memory changes made by another thread.
In your example, the child thread does not see the up-to-date value of flag. (It is not that the conditions themselves are incorrect or "don't work". They are actually getting stale inputs. This is "garbage in, garbage out".)
The Java Language Specification sets out precisely the conditions under which one thread is guaranteed to see (previous) writes made by another thread. This part of the spec is called the Java Memory Model, and it is in JLS 17.4. There is a more easy to understand explanation in Java Concurrency in Practice by Brian Goetz et al.
Note that the unexpected behavior could be due to the JIT deciding to keep the flag in a register. It could also be that the JIT compiler has decided it does not need force memory cache write-through, etcetera. (The JIT compiler doesn't want to force write-through on every memory write to every field. That would be a major performance hit on multi-core systems ... which most modern machines are.)
The Java interruption mechanism is yet another way to deal with this. You don't need any synchronization because the method calls that. In addition, interruption will work when the thread you are trying to interrupt is currently waiting or blocked on an interruptible operation; e.g. in an Object::wait call.
Because the variable is not modified in that thread, the JVM is free to effectively optimize the check away. To force an actual check, use the volatile keyword:
public volatile boolean flag = false;

Understanding deadlock [duplicate]

This question already has answers here:
Mutithreading with System.out.format and System.out.println
(4 answers)
Closed 5 years ago.
I am trying to understand how to create a deadlock from https://docs.oracle.com/javase/tutorial/essential/concurrency/deadlock.html.
Instead of copy and pasting the sample code, I chose to write it by myself.
The last line in the link says "neither block will ever end because each thread is waiting for the other to exit bow" but never mentions about System.out.format.
I then wrote the below code and it never entered deadlock
public class DeadlockTest {
static class Resource {
public synchronized void test1(Resource r) {
System.out.print("test1");
r.test2();
}
public synchronized void test2() {
System.out.print("test2");
}
}
public static void main(String... a) {
final Resource r1 = new Resource();
final Resource r2 = new Resource();
new Thread(new Runnable() {
public void run() {
r1.test1(r2);
}
}).start();
new Thread(new Runnable() {
public void run() {
r2.test1(r1);
}
}).start();
}
}
So I tried to compare line by line and found that only the print statement is wrong. Instead of using System.out.format I used System.out.print. So the code never ran in to a dead lock situation. I then changed it to System.out.format and I was able to simulate a dead lock.
I even copied the example code from the link, changed the format statement to print/println and it was not entering deadlock.
Can anyone please explain how to exactly create a deadlock?
I took your code to test it. It indeed ran fine.
Only when I added a Thread.sleep(100) or the String.format in test1, it blocked. It seems as if your "work" method (print) is too fast. Before the second thread can cause the block by calling test1, the first thread is already finished with test2.
To stay in the tutorials example: Your threads did not in fact "bow at each other at the same time", but only "very quickly after one another". Make the bowing a little slower and you increase the chances of them bowing at the same time (still not guaranteed, e.g. if the system takes longer to schedule the second thread).

Synchronized Block inside the run method

Does using a synchronized block inside the run method makes any sense? I thought it does, as long as I'm using a relevant lock, not the instance of Runnable containing this run method. Reading the answers to similar questions on stackoverflow seemed to confirm this. I tried to write some simple code to test it and the synchronized block inside the run method doesn't prevent from data corruption:
public class Test {
public Test() {
ExecutorService es = Executors.newCachedThreadPool();
for (int i = 0; i < 1000; i++) {
es.execute(new Runnable() {
#Override
public void run() {
synchronized (lock) {
sum += 1;
}
}
});
}
es.shutdown();
while(!es.isTerminated()) {
}
}
private int sum = 0;
private final Object lock = new Object();
public static void main(String[] args) {
Test t = new Test();
System.out.println(t.sum);
}
}
Why this code generates incorrect results? Is this because the synchronized block or some other mistake? I feel like I'm missing something basic here.
It's possible your executor encounters some sort of unexpected error. If that happens you won't know it because you are not getting any return value to check.
Try switching to submit() instead of execute() and store a list of Future instances the Executor gives you. If the final sum is less than 1000, iterate the futures and get() each one. If an exception is raised you'll see what happened with that particular runnable task.
Apart from your simple example, which looks OK, you should be careful with synchronization in Runnables to prevent them from blocking each other when one Runnable waits for some resource to be released only by another Runnable later in the queue that has not started yet and never will since the current waiting Runnable must finish first.
With enough worker Threads executing the jobs this is less likely to occur, though.

The code example which can prove "volatile" declare should be used

Currently I can't understand when we should use volatile to declare variable.
I have do some study and searched some materials about it for a long time and know that when a field is declared volatile, the compiler and runtime are put on notice that this variable is shared and that operations on it should not be reordered with other memory operations.
However, I still can't understand in what scenario we should use it. I mean can someone provide any example code which can prove that using "volatile" brings benefit or solve problems compare to without using it?
Here is an example of why volatile is necessary. If you remove the keyword volatile, thread 1 may never terminate. (When I tested on Java 1.6 Hotspot on Linux, this was indeed the case - your results may vary as the JVM is not obliged to do any caching of variables not marked volatile.)
public class ThreadTest {
volatile boolean running = true;
public void test() {
new Thread(new Runnable() {
public void run() {
int counter = 0;
while (running) {
counter++;
}
System.out.println("Thread 1 finished. Counted up to " + counter);
}
}).start();
new Thread(new Runnable() {
public void run() {
// Sleep for a bit so that thread 1 has a chance to start
try {
Thread.sleep(100);
} catch (InterruptedException ignored) {
// catch block
}
System.out.println("Thread 2 finishing");
running = false;
}
}).start();
}
public static void main(String[] args) {
new ThreadTest().test();
}
}
The following is a canonical example of the necessity of volatile (in this case for the str variable. Without it, hotspot lifts the access outside the loop (while (str == null)) and run() never terminates. This will happen on most -server JVMs.
public class DelayWrite implements Runnable {
private String str;
void setStr(String str) {this.str = str;}
public void run() {
  while (str == null);
  System.out.println(str);
}
public static void main(String[] args) {
  DelayWrite delay = new DelayWrite();
  new Thread(delay).start();
  Thread.sleep(1000);
  delay.setStr("Hello world!!");
}
}
Eric, I have read your comments and one in particular strikes me
In fact, I can understand the usage of volatile on the concept
level. But for practice, I can't think
up the code which has concurrency
problems without using volatile
The obvious problem you can have are compiler reorderings, for example the more famous hoisting as mentioned by Simon Nickerson. But let's assume that there will be no reorderings, that comment can be a valid one.
Another issue that volatile resolves are with 64 bit variables (long, double). If you write to a long or a double, it is treated as two separate 32 bit stores. What can happen with a concurrent write is the high 32 of one thread gets written to high 32 bits of the register while another thread writes the low 32 bit. You can then have a long that is neither one or the other.
Also, if you look at the memory section of the JLS you will observe it to be a relaxed memory model.
That means writes may not become visible (can be sitting in a store buffer) for a while. This can lead to stale reads. Now you may say that seems unlikely, and it is, but your program is incorrect and has potential to fail.
If you have an int that you are incrementing for the lifetime of an application and you know (or at least think) the int wont overflow then you don't upgrade it to a long, but it is still possible it can. In the case of a memory visibility issue, if you think it shouldn't effect you, you should know that it still can and can cause errors in your concurrent application that are extremely difficult to identify. Correctness is the reason to use volatile.
The volatile keyword is pretty complex and you need to understand what it does and does not do well before you use it. I recommend reading this language specification section which explains it very well.
They highlight this example:
class Test {
static volatile int i = 0, j = 0;
static void one() { i++; j++; }
static void two() {
System.out.println("i=" + i + " j=" + j);
}
}
What this means is that during one() j is never greater than i. However, another Thread running two() might print out a value of j that is much larger than i because let's say two() is running and fetches the value of i. Then one() runs 1000 times. Then the Thread running two finally gets scheduled again and picks up j which is now much larger than the value of i. I think this example perfectly demonstrates the difference between volatile and synchronized - the updates to i and j are volatile which means that the order that they happen in is consistent with the source code. However the two updates happen separately and not atomically so callers may see values that look (to that caller) to be inconsistent.
In a nutshell: Be very careful with volatile!
A minimalist example in java 8, if you remove volatile keyword it will never end.
public class VolatileExample {
private static volatile boolean BOOL = true;
public static void main(String[] args) throws InterruptedException {
new Thread(() -> { while (BOOL) { } }).start();
TimeUnit.MILLISECONDS.sleep(500);
BOOL = false;
}
}
To expand on the answer from #jed-wesley-smith, if you drop this into a new project, take out the volatile keyword from the iterationCount, and run it, it will never stop. Adding the volatile keyword to either str or iterationCount would cause the code to end successfully. I've also noticed that the sleep can't be smaller than 5, using Java 8, but perhaps your mileage may vary with other JVMs / Java versions.
public static class DelayWrite implements Runnable
{
private String str;
public volatile int iterationCount = 0;
void setStr(String str)
{
this.str = str;
}
public void run()
{
while (str == null)
{
iterationCount++;
}
System.out.println(str + " after " + iterationCount + " iterations.");
}
}
public static void main(String[] args) throws InterruptedException
{
System.out.println("This should print 'Hello world!' and exit if str or iterationCount is volatile.");
DelayWrite delay = new DelayWrite();
new Thread(delay).start();
Thread.sleep(5);
System.out.println("Thread sleep gave the thread " + delay.iterationCount + " iterations.");
delay.setStr("Hello world!!");
}

Categories