Understanding deadlock [duplicate] - java

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).

Related

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;

Java IO's implements on thread variable sharing [duplicate]

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 was confused with a code snippet like this:
public class LearnTest {
private static boolean tag = true;
private static int i = 0;
public static void main(String[] args) {
new Thread(new Runnable() {
#Override
public void run() {
while (tag) {
//System.out.println("ok");
i++;
}
}
}).start();
try {
Thread.sleep(1000);
}catch (Exception e) {
e.printStackTrace();
}
tag = false;
System.out.println(i);
}
}
In the code, we have a new-thread and main-thread.The result about this code will be a random value of i and the new-thread will not exit.Because new-thread will not get the new tag value.
if we change the define of tag which will be decorated with volatile, it will print some value of i and new-thread will exit. Because volatile will keep the visibility for all thread.
But when I cannel the comment for the commentted code line,and thetag will not be decorated witch volatile,it will print some "ok" and exit.
why?
what I suppose is that Java's IO will do something like synchronized, it will force the tag side value of new-thread to refresh from main shared memory.
This's corret?
Without volatile the thread is not guaranteed to see changes to the value. It may see them.
In this case adding the System.out.println() results (apparently) in the value being removed from the cache, so it's fetched from the main memory at some point. Without the println() the value remains in cache, and you get the infinite (or at least very long) loop.
That's one difficulty with concurrent programming, sometimes code may appear to work correctly, but there's no way to be certain it always works correctly.

Multithreading "unpredictable" behavior [duplicate]

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();
}
}

Conditional statement at the beginning of a while loop doesn't get checked [duplicate]

This question already has an answer here:
Loop doesn't see value changed by other thread without a print statement
(1 answer)
Closed 7 years ago.
I've noticed this bug (if it is a bug) and decided to make a test environment. Does anyone know if this is an actual problem or is it just me?
import java.util.Random;
public class Start {
public static boolean value;
public static void main(String[] args){
Thread thread = new Thread(){
#Override
public void run(){
random();
}
};
thread.start();
while(true){
if(value) System.out.println("Done");
}
}
public static void random(){
while(true){
value = new Random().nextInt(5) == 0;
}
}
}
I would expect this code to be spamming out "Done"s, but instead I get a bunch at the beginning and then no additions. When I modify the code as so:
while(true){
System.out.print(""); //Modification
if(value) System.out.println("Done");
}
It starts spamming the "Done"s. Anyone know what's up?
NOTE: I have tested this in an Eclipse environment and a compiled jar while using jdk 1.8.0 v.25 and jre 1.8.0 v.51.
I suspect that you hit a compiler optimization called hoisting - it recognizes that you overwrite value without having these changes "visible" to other threads and that's why it optimizes at some point and stops printing.
This behavior will change to what is likely the "wanted" behavior once you'll declare value as volatile - then updates to it become visible to other threads and then the printings will keep on forever.

wait() - notify() mechanism in java malfunctioning in a strange way [duplicate]

This question already has answers here:
Why should wait() always be called inside a loop
(11 answers)
Closed 7 years ago.
I've tried reading some answers to similar questions here (I always do that) but did not find (or did not understand?) the answer to this particular issue.
I am implementing a fairly simple consumer-producer class, which receives elements to a list from a different thread and consumes them repeatedly. The class has the following code:
public class ProduceConsume implements Runnable
{
LinkedList<Integer> _list = new LinkedList<Integer>();
public synchronized void produce(Integer i)
{
_list.add(i);
notify();
}
public void run()
{
while(true)
{
Integer i = consume();
// Do something with the integer...
}
}
private synchronized Integer consume()
{
if(_list.size() == 0)
{
try
{
wait();
}
catch(InterruptedException e){}
return _list.poll();
}
}
}
The problem is - it usually works fine, but sometimes, the execution gets to
return _list.poll();
with the list still empty. I can't wrap my head around it - am I doing something terribly wrong? Shouldn't the runnable thread, which repeatedly tries to poll detect a zero length list, wait, and be awakened only after the producer method is done, hence making the list non-empty?
Nothing else "touches" the class from the outside, except for calls to produce. No other threads are synchronized on the runnable class.
By the way, for several reasons, I wish to use my own variant and not classes such as CopyOnWriteArrayList, etc.
Thanks! Any help would be greatly appreciated.
P.S - I have not used the wait-notify many times, but when I did, in the past, it worked. So if I apologize if I made some huge stupid error!
As the Javadoc for Object.wait states
As in the one argument version, interrupts and spurious wakeups are possible, and this method should always be used in a loop:
synchronized (obj) {
while (<condition does not hold>)
obj.wait();
... // Perform action appropriate to condition
}
Additionally, you shouldn't ignore an exception like InterruptedException. This will look like a spurious wake up and as you say produces an error.
private synchronized Integer consume() {
try {
while (_list.isEmpty())
wait();
return _list.poll();
} catch(InterruptedException e) {
throw new IllegalStateException("Interrupted");
}
}
Since wait releases the lock you can't reason based on conditions tested before it started waiting, assuming the condition must have changed once wait is exited is not valid. You need to call wait in a loop, so that once the thread ceases waiting and takes the lock again, it checks that the condition it's waiting for has the expected value:
private synchronized Integer consume()
{
try {
while (_list.size() == 0) {
wait();
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return _list.poll();
}
From the Oracle tutorial:
Note: Always invoke wait inside a loop that tests for the condition being waited for.
Also it's not safe to assume that just because wait returned that something sent a notification. wait can return even if there is no notification (the spurious wakeup).
It's hard to say what caused what you're seeing without a complete working example.
The linked Oracle tutorial page has a Producer Consumer example you might want to look at.

Categories