Reputation: 67
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?
Upvotes: 2
Views: 118
Reputation: 328800
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();
}
}
Upvotes: 4
Reputation: 1812
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.
Upvotes: 3
Reputation: 361
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();
}
Upvotes: 0
Reputation: 3439
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.
Upvotes: 0
Reputation: 8147
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.
Upvotes: 0