Please refer to the code below
package com.test;
public class DeadLock {
private void method1() {
synchronized (Integer.class) {
method2();
}
}
private void method2() {
synchronized (Integer.class) {
System.out.println("hi there");
}
}
public static void main(String[] args) {
new DeadLock().method1();
}
}
As per my understanding, the code in method2 should not be executed in any case, since method1 holds the lock on Integer.class and method2 tries to access the lock on Integer.class again. But to my surprise, the code runs fine and it prints "hi there" to the console. Can someone clarify?
Locks are owned by threads. If your thread already owns a lock, Java assumes that you don't need to acquire it a second time and just continues.
You'll get a deadlock if you start a second thread in method1() while holding the lock and the second thread executes the method method2().
If you prefer code, then synchronized works like this:
Lock lock = Integer.class.getLock();
boolean acquired = false;
try {
if(lock.owner != Thread.currentThread()) {
lock.acquire();
acquired = true;
}
...code inside of synchronized block...
} finally {
if(acquired) lock.release();
}
Here is code to demonstrate the deadlock. Just set runInThread to true:
package com.test;
public class DeadLock {
private void method1() {
synchronized (Integer.class) {
boolean runInThread = false;
if( runInThread ) {
Thread t = new Thread() {
#Override
public void run() {
method2();
}
};
t.start();
try {
t.join(); // this never returns
} catch( InterruptedException e ) {
e.printStackTrace();
}
} else {
method2();
}
}
}
private void method2() {
System.out.println("trying to lock");
synchronized (Integer.class) {
System.out.println("hi there");
}
}
public static void main(String[] args) {
new DeadLock().method1();
}
}
It seems you have misunderstood the concept.
A method never acquires a lock, the instance on which the method is invoked serves as a lock in case of synchronized method and in case of synced block the thread acquires the lock on specified object.
Here the instance acquires the lock on Integer.class and then it goes on to execute method2.
There is no case of deadlock as in your case thread continues for the execution of the method that you're calling inside method1. So there is no deadlock that happens.
your code is equivalent to:
synchronized (Integer.class) {
synchronized (Integer.class) {
System.out.println("hi there");
}
}
if the thread acquired the lock and entered the first synchronized block it will have no problem accessing the 2nd
to produce a deadlock the call to method2 should be executed by a different thread.
synchronized (Integer.class) {
method2();
}
when you calling this method2(); then its not giving lock to any kind of mehtod its continues goes to the method that you are calling means this.
private void method2() {
synchronized (Integer.class) {
System.out.println("hi there");
}
}
and after completing its returning. so there is no case of dead lock. hope this explanation helps.
As already said, one thread can access more than one synchronised blocks when no other thread already blocks it. In that situation the same thread can reenter synchronised block because it already holds it from method1.
To cause the deadlock you have to use two thread at least and two different locks. It have to access two locks in the reverse order. Check out that code:
private void method1() throws InterruptedException
{
synchronized (Integer.class)
{
System.out.println(Thread.currentThread().getName() + " hi there method 1");
Thread.sleep(1000);
method2();
}
}
private void method2() throws InterruptedException
{
synchronized (Double.class)
{
System.out.println(Thread.currentThread().getName() + " hi there method 2");
Thread.sleep(1000);
method1();
}
}
public static void main(String[] args) throws InterruptedException
{
new Thread()
{
#Override
public void run()
{
try
{
new DeadLock().method1();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}.start();
new DeadLock().method2();
}
Related
public class Test2 {
static int count;
public static void main(String[] args) {
final Test2 t1 = new Test2();
final Test2 t2 = new Test2();
new Thread(new Runnable() {
#Override
public void run() {
t1.foo();
}
}).start();
new Thread(new Runnable() {
#Override
public void run() {
t1.bar();
}
}).start();
new Thread(new Runnable() {
#Override
public void run() {
t2.foo();
}
}).start();
}
public static synchronized void foo() {
synchronized (Test2.class) {
System.out.println("run bar"+count++);
try {
Thread.sleep(100000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static synchronized void bar() {
System.out.println("run bar");
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
above are codes which I tried.When I write all codes in one Class synchronized (Test2.class) and I found something strange happened.After I invoked foo() method I can't invoke bar() method immediately. what I think it lock same object.how to explain this strange thing.
All 3 of the threads your code starts acquire the same lock, on the Test2 class. When you write a method starting with
static synchronized
that means it has to acquire the lock on the class object.
The synchronized block in the foo method is redundant. It specifies using the same class to lock on as using static synchronized. Since intrinsic locks are reentrant this doesn't cause a problem.
Anyway, each of your threads acquires the lock, runs to completion, then releases the lock. Since you are locking on the class and not on an instance it doesn't matter which instance of Test2 your threads use, they still acquire the same lock and execute one at a time.
When I ran this I got the following output:
c:\Users\ndh>java Test2
run bar0
run bar1
run bar
The order in which these threads run is up to the scheduler. It would seem reasonable to guess that the Runnable calling t1.foo got a head start -- since it was created and started first it's likely to have a window where it won't have any competition acquiring the lock.
I'd use a volatile condition variable, but I think volatile is redundant. Besides I'm not quite sure I understood this point from https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/package-summary.html#MemoryVisibility correctly:
An unlock (synchronized block or method exit) of a monitor
happens-before every subsequent lock (synchronized block or method
entry) of that same monitor. And because the happens-before relation
is transitive, all actions of a thread prior to unlocking
happen-before all actions subsequent to any thread locking that
monitor.
So synchronized blocks are called subsequently. But are results of assignments performed in a synchronized block visible to all the subsequent synchronized blocks?
Here is a sample app.
package sample;
public class Foo {
private boolean shouldWait;
private final Object lock = new Object();
void blockThread() {
synchronized (lock) {
shouldWait = true;
while (shouldWait) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
void notifyThread() {
synchronized (lock) {
shouldWait = false;
lock.notify();
}
}
}
Test.
package sample;
public class Main {
private static Foo foo = new Foo();
public static void main(String[] args) {
new Thread(new Runnable() {
#Override
public void run() {
foo.blockThread();
}
}).start();
try {
Thread.sleep(200);
} catch (InterruptedException e) {
}
new Thread(new Runnable() {
#Override
public void run() {
foo.notifyThread();
}
}).start();
}
}
So synchronized blocks are called subsequently. But are results of assignments performed in a synchronized block visible to all the subsequent synchronized blocks?
Yes. volatile writes have the same relationship. All actions prior to a volatile write happens-before all subsequent reads.
I am trying to understand the use of Synchronized block.
In the below program, Inside a produce and consumer method I have created a synchronized block and if I lock it by using lock1(object). I am getting the following error, why is this, why am i getting this error?
I am aware that by replacing lock1 by this(same class). I can get rid of the error. I still want to know why this error as everything seems very logical to me.
Program
import java.util.Scanner;
public class Worker {
private Object lock1 = new Object();
private Object lock2 = new Object();
public void produce() throws InterruptedException {
synchronized (lock1) {
System.out.println("Producer thread running");
wait();
System.out.println("Producer resumed");
}
}
public void consumer() throws InterruptedException {
Scanner scanner = new Scanner(System.in);
Thread.sleep(2000);
synchronized (lock1) {
System.out.println("Waiting for return key");
scanner.nextLine();
System.out.println("return key is pressed");
notify();
Thread.sleep(5000);
System.out.println("Consumer is over");
}
}
public void main() {
Thread t1 = new Thread(new Runnable() {
public void run() {
try {
produce();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread t2 = new Thread(new Runnable() {
public void run() {
try {
consumer();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Exception in thread "Thread-0" java.lang.IllegalMonitorStateException
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:503)
at Worker.produce(Worker.java:14)
at Worker$1.run(Worker.java:43)
at java.lang.Thread.run(Unknown Source)
synchronized (lock1) {
System.out.println("Producer thread running");
wait();
System.out.println("Producer resumed");
}
You acquire the monitor of lock1 and then proceed to wait on this which fails because, as the documentation of Object#wait states,
The current thread must own this object's monitor.
You need to call lock1.wait() and lock1.notify(). You can only call wait() or notify() on an object on which you hold the lock (lock1 in this case).
In the synchronized block the current thread is the owner of the synchronization object's monitor.
In your case it is lock1.
According to the javadoc of Object.wait()
The current thread must own this object's monitor.
and Object.notify()
This method should only be called by a thread that is the owner of this object's monitor.
you must change your code to
synchronized (lock1) {
System.out.println("Producer thread running");
lock1.wait();
System.out.println("Producer resumed");
}
and
synchronized (lock1) {
System.out.println("Waiting for return key");
scanner.nextLine();
System.out.println("return key is pressed");
lock1.notify();
Thread.sleep(5000);
System.out.println("Consumer is over");
}
To call wait() and notify() you need to own the object's monitor you want to call these two methods.
Link to javadoc Object.wait()
Citation from above link:
The current thread must own this object's monitor.
I am showing how I fixed the producer-consumer problem.
I have using different way then you. I think this will help you..
And the to make any block or method synchronized their are some condition :
synchronized methods prevent more than one thread from accessing an
object's critical method code simultaneously.
You can use the synchronized keyword as a method modifier, or to start a
synchronized block of code.
To synchronize a block of code (in other words, a scope smaller than the
whole method), you must specify an argument that is the object whose lock
you want to synchronize on.
While only one thread can be accessing synchronized code of a particular
instance, multiple threads can still access the same object's unsynchronized code.
static methods can be synchronized, using the lock from the
java.lang.Class instance representing that class.
All three methods—wait(), notify(), and notifyAll()—must be
called from within a synchronized context! A thread invokes wait() or
notify() on a particular object, and the thread must currently hold the lock
on that object.
class P implements Runnable{
Data d;
P(Data d){
this.d = d;
new Thread(this,"Producer").start();
}
public void run(){
for(int i=0; i<=20; i++){
d.set(i);
System.out.println("put -> "+i);
}
}
}
class C implements Runnable{
Data d;
C(Data d){
this.d = d;
new Thread(this,"Consumer").start();
}
public void run(){
for(int i=0; i<=20; i++){
int n = d.get();
System.out.println("get -> "+n);
}
}
}
class Data{
int n;
boolean valueset=false;
synchronized void set(int n){
if(valueset){
try{
wait();
}catch(Exception e){
System.out.println("set -> Exception "+e);
}
}
this.n = n ;
valueset=true;
notify();
}
synchronized int get(){
if(!valueset){
try{
wait();
}catch(Exception e){
System.out.println("get -> Exception "+e);
}
}
valueset=false;
notify();
return n ;
}
}
class PC{
public static void main(String[] args){
Data d = new Data();
new P(d);
new C(d);
}
}
You can download solution of producer consumer from here :
https://www.mediafire.com/?52sa1k26udpxveu
My code gives me a problem.
My code throws IllegalMonitorStateException in setStr which is in Hoge class.
I change Hoge.class into this in setStr. My code correctly finished!
But why did it finish normally?
public class Sample {
static Hoge gh = new Hoge();
static Hoge gh2 = new Hoge();
public static void main(String[] args) {
new Thread() {
private Hoge h2 = gh;
public void run() {
System.out.println("start initialize");
h2.setStr("BazzBazz");
System.out.println("end initialize");
System.out.println("start thread 1");
System.out.println(h2.getStr("thread-1"));
System.out.println("end thread 1");
}
}.start();
new Thread() {
private Hoge h2 = gh2;
public void run() {
System.out.println("start thread 2");
System.out.println(h2.getStr("thread-2"));
System.out.println("end thread 2");
}
}.start();
}
}
class Hoge {
private String fuga = "fugafuga";
public void setStr(String str) {
synchronized(Hoge.class) { //<-HERE ! change "Hoge.class" into "this".
fuga = str;
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
String getStr(String suffix) {
synchronized(Hoge.class) {
return suffix+ fuga;
}
}
}
YoursetStr method should be like this:
public void setStr(String str) {
synchronized(Hoge.class) { //<-HERE ! change "Hoge.class" into "this".
fuga = str;
try {
Hoge.class.wait();//call wait on Hoge.class
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
You should use Hoge.clas.wait() instead of wait(). Why?
Because , as specified in oracle documentation about wait() :
This method should only be called by a thread that is the owner of
this object's monitor.
i.e a thread can't invoke a wait on an object until it owns that object's lock. Otherwise it will throw IllegalMonitorStateException . Here , you are acquiring lock on object of Class of Hoge(i.e Hoge.class) called as class level lock , but was calling wait on the current object of Hoge(this). So it was leading to IllegalMonitorStateException. That's why your code was working fine when you acquiring lock on the current object (this) because wait() in that case was called on the current object (this) itself.
Because this in gh and gh2 are different, this is an instance of Hoge.
So when use Hoge.class, there is noly one synchronized lock, rather than using this which will use two different lock.
public class Main2 {
public static void main(String[] args) {
new Test2().start();
new Test2().start();
}
}
class Test2 extends Thread {
#Override
synchronized public void run() {
try {
System.out.println("begin wait");
wait();
} catch (Exception ex) {
}
}
}
As the actual result of running the test:
begin wait,
begin wait,
two times from the two threads.
Contrast to the expected result:
begin wait,
only one time from one of the two threads because wait() is called inside the synchronized run() method.
Why could call to Object's wait() break thread synchronization?
Thans a lot!
public class Main3 {
public static void main(String[] args) {
Test3 t = new Test3();
new Thread(t).start();
new Thread(t).start();
}
}
class Test3 implements Runnable {
synchronized public void run() {
try {
System.out.println("begin wait");
wait();
} catch (Exception ex) {
}
}
}
#akf & #Sean Owen
Thanks for your replies. Sorry for my mistake, now i modified the code to place the synchronization on the same object's run(), the result remained: begin wait, begin wait, two times.
#akf
wait will release the lock that
synchronize has grabbed, and will be
re-gotten once the thread is notified.
Could you elaborate a little bit?
The object that you are synchronizing on in this example is not the class, but the instance, so each new Test2 object would be synchronizing on a different monitor.
The method you might be looking for here is sleep, not wait. wait will release the lock that synchronized has grabbed, and will be re-gotten once the thread is notified.
Note that for your test to work correctly, you will need to lock on a common object. If you want to see wait in action, I have thrown together a simple app that will pop up a frame with a "Notify" button. Two threads will be started that wait on a common object and are in turn notified when the button is pressed.
public static void main(String[] args)
{
final Object lock = new Object();
final JFrame frame = new JFrame("Notify Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton button = new JButton("Notify");
button.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent evt) {
synchronized(lock) {
lock.notify();
}
}
});
frame.add(button);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
frame.setVisible( true );
}
});
new Thread(new Runnable() {
public void run() {
synchronized(lock) {
try {
System.out.println("1. starting");
lock.wait();
System.out.println("1. step 1");
lock.wait();
System.out.println("1. step 2");
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
}
}).start();
new Thread(new Runnable() {
public void run() {
synchronized(lock) {
try {
System.out.println("2. starting");
lock.wait();
System.out.println("2. step 1");
lock.wait();
System.out.println("2. step 2");
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
}
}).start();
}
For a simple explanation of wait, the JavaDoc is always a good place to start:
Causes the current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object. In other words, this method behaves exactly as if it simply performs the call wait(0).
The current thread must own this object's monitor. The thread releases ownership of this monitor and waits until another thread notifies threads waiting on this object's monitor to wake up either through a call to the notify method or the notifyAll method. The thread then waits until it can re-obtain ownership of the monitor and resumes execution.
You have two different Test2 objects. Synchronized methods lock on the object. They are not acquiring the same lock, so no it should print twice.
an simple example that can help you is this:
public class test {
public static void main(String[] args) {
Prova a=new Prova();
new Test2(a).start();
new Test2(a).start();
}
}
class Prova{
private boolean condition;
public void f(){
while(condition){
//Thread.currentThread Returns a reference to the currently executing thread object.
//Thread.getName() return name Thread
System.out.println(Thread.currentThread().getName()+" begin wait");
try{
wait();
}catch(InterruptedException c){return;}
}
System.out.println(Thread.currentThread().getName()+" first to take the mutex");
condition=true;
}
}
class Test2 extends Thread {
private Prova a;
private static boolean condition;
public Test2(Prova a){
this.a=a;
}
#Override
public void run() {
synchronized(a){
try {
a.f();
} catch (Exception ex) {
}
}
}
}
in this case the two threads synchronize an object, the first taking the lock release message, the second one waits. in this example uses the condition variable
summary to wait/notify mechanism:
1)current thread reaches one object's synchronized code block which contains the call to wait(), it competes with other threads for the lock(the object's monitor), as winner it executes the block till the call to wait() encounters.
2)by calling wait(), current thread releases the lock to other competing threads, then halts execution, wait for notify being sent from another thread who succeeds in obtaining the lock.
JavaDoc:
A thread becomes the owner of
the object's monitor in one of three
ways:
•By executing a synchronized instance
method of that object.
•By executing
the body of a synchronized statement
that synchronizes on the object.
•For
objects of type Class, by executing a
synchronized static method of that
class.
3)another thread reaches the same object's yet another synchronized code block which contains the call to notify/notifyAll(), it competes with other threads for the lock, as winner it executes the block till finishing the call to notify/notifyAll(). It will release the lock either by call to wait() or at the end of the execution on the block.
4)upon receiving notify/notifyAll(), current thread competes for the lock, as winner the execution continues where it has halted.
simple example:
public class Main3 {
public static void main(String[] args) {
Test3 t = new Test3();
new Thread(t).start();
new Thread(t).start();
try {
Thread.sleep(1000);
} catch (Exception ex) {
}
t.testNotifyAll();
}
}
class Test3 implements Runnable {
synchronized public void run() {
System.out.println(Thread.currentThread().getName() + ": " + "wait block got the lock");
try {
wait();
} catch (Exception ex) {
}
System.out.println(Thread.currentThread().getName() + ": " + "wait block got the lock again");
try {
Thread.sleep(1000);
} catch (Exception ex) {
}
System.out.println(Thread.currentThread().getName() + ": " + "bye wait block");
}
synchronized void testNotifyAll() {
System.out.println(Thread.currentThread().getName() + ": " + "notify block got the lock");
notifyAll();
System.out.println(Thread.currentThread().getName() + ": " + "notify sent");
try {
Thread.sleep(2000);
} catch (Exception ex) {
}
System.out.println(Thread.currentThread().getName() + ": " + "bye notify block");
}
}
output:
Thread-0(or 1): wait block got the
lock
Thread-1(or 0): wait block got
the lock
main: notify block got the
lock
main: notify sent
main: bye notify block
Thread-0(or 1): wait block
got the lock again
Thread-0(or 1): bye
wait block
Thread-1(or 0): wait block
got the lock again
Thread-1(or 0): bye
wait block