Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reentrant locking

A bit of help please, consider the bit of code below.

public class Widget {
    public synchronized void doSomething() {
        ...
    }
}

public class LoggingWidget extends Widget {
    public synchronized void doSomething() {
        System.out.println(toString() + ": calling doSomething");
        super.doSomething();
    }
}

I read that when doSomething() in LoggingWidget is called, the JVM will try to acquire a lock on LoggingWidget first and then on Widget.

I am curious to know the reason. Is it because the JVM knows that doSomething() has a call to super.doSomething() or because calling a subclass method will always acquire a lock on the superclass as well.

Cheers

like image 965
CaptainHastings Avatar asked Jul 09 '09 15:07

CaptainHastings


People also ask

What is a reentrant Lock in Java?

What Is a Reentrant Lock? A reentrant lock is a mutual exclusion mechanism that allows threads to reenter into a lock on a resource (multiple times) without a deadlock situation. A thread entering into the lock increases the hold count by one every time.

What is the fairness of a reentrant Lock?

Reentrant Locks also offer a fairness parameter, by which the lock would abide by the order of the lock request i.e. after a thread unlocks the resource, the lock would go to the thread which has been waiting for the longest time. This fairness mode is set up by passing true to the constructor of the lock.

Do I need a reentrant async lock in my code?

If you need a reentrant async lock — you are out of luck and would have to get rid of lock reentry in your code-base instead. If you are using some 3rd party reentrant async lock — you are advised to get rid of it as well.

Why read lock is not allowed when using reentrant read write lock?

If any thread is using the write lock of Reentrant Read Write Lock pair, read lock on resource is not allowed. We use write lock from Reentrant Read Write Lock pair with write code. Acquiring the lock before, then calling the write task in try block and releasing the write lock in finally block.


2 Answers

You are mistaken - the locks are obtained at the instance level. There is only one lock in your example because there is only one instance created when you say:

Widget w = new LoggingWidget

You can view locks (also known as monitors, mutexes or semaphores) as being individually "attached" to every object instance in the JVM.

If you had another synchronized method on the LoggingWidget subclass, you would see this to be true. It would not be possible to call this (new) method and the doSomething method at the same time [with different threads on same object].

This also holds true for another synchronized method on the superclass (i.e. it is not affected in any way by methods being overridden).

like image 104
oxbow_lakes Avatar answered Oct 19 '22 09:10

oxbow_lakes


public synchronized void doSomething() {
    System.out.println(toString() + ": calling doSomething");
    super.doSomething();
}

is the same as:

public void doSomething() {
    synchronized (this) {
        System.out.println(toString() + ": calling doSomething");
        super.doSomething();
    }
}

You're locking on the instance, not the class. So when super.doSomething() is called, you already have that instance locked.

like image 5
bajafresh4life Avatar answered Oct 19 '22 11:10

bajafresh4life