Reentrant blocking - Java concurrency in practice

Here is some sample code for relocking with "Java concurrency in practice":

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


}

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

      

The book explains that in the above code ... "Since the doSomething methods on the widget and the LoggingWidget are synchronized, each tries to acquire a lock on the widget before proceeding."

I followed the above code to observe the internal locking. The above quote seems to imply that the thread is acquiring an internal lock on the Widget, but I noticed that the thread is acquiring the lock on the LoggingWidget. I'm not sure how to check the collection account, so I couldn't see it.

Is the book using the LoggingWidget / Widget names interchangeable, or should I keep an eye on locking the Widget object?

Edit: full excerpt

Reentrancy makes it easy to encapsulate locking behavior and therefore makes it easier to develop object-oriented parallel code. Without the reenterator, the very natural code in Listing 2.7 in which a subclass cancels a synchronized method and then calls the superclass would be a dead end. Because the doSomething methods in Widgets and LoggingWidget are synchronized, each one tries to acquire a lock on the widget before continuing. But if the internal locks were not reentrant, calling super.doSomething would never be able to acquire the lock, because it would be considered already held, and the thread would constantly stop waiting for the lock, it could never acquire. Reentrancy saves us from a dead end in these situations.

+3


source to share


2 answers


Yes, the author uses LoggingWidget / Widget interchangeably, because according to OOP inheritance, the LoggingWidget is also a Widget object. The example will create only one instance of the object, which will be used as a sync monitor for re-entry.



+3


source


I need to see an excerpt to give you a specific answer. You can create these classes in different ways. The lock is held on the object, so the reference doesn't matter. To illustrate this ...

This class structure closely mimics yours.

public class GenericTest {
    public static void main(String... args) {
        Sub sub = new Sub();
        sub.go();
    }

    public synchronized void go() {
        System.out.println("Parent");
    }
}

class Sub extends GenericTest {
    @Override
    public synchronized void go() {
        System.out.println("Child");
        super.go();
    }
}

      

Run this program and stop executing further lines after acquiring the lock with a method of your pleasure (for example, System.in.read ()). Find the pid of the java program and open it in Jconsole. Go to the section threads

and highlight it each time the lock has been acquired. You will see the following tracks.



my.package.common.GenericTest.go(GenericTest.java:30)
   - locked my.package.common.Sub@4c767286
my.package.common.Sub.go(GenericTest.java:42)
   - locked my.package.common.Sub@4c767286

      

Since this method is a member variable, the lock is on the current object ( this

) that executed this method. Note that both locks are on Sub@4c767286

.

[EDIT]

Edited my answer to suit your specific case.

+6


source







All Articles