Background:
I'm reading Java Concurrency in Practice, and Listing 2.7 has the following code. The example states that this code only functions because monitor locks are re-entrant.
I would have originally thought that when you called super.doSomething() then it would have acquired a lock on the base class object and not the derived class object. That would mean this situation would not require re-entrancy. Having said this, I also understand that both base class and derived class methods can alter base class fields, so the lock they use must be common (meaning I was obviously mistaken).
Question:
Is there one "intrinsic" lock per object in an inheritance hierarchy, or one "intrinsic" lock associated with the most derived object (or least derived object) in the hierarchy only?
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 would have originally thought that when you called super.doSomething() then it would have acquired a lock on the base class object and not the derived class object.
There's only one object - if you create an instance of LoggingWidget, there's only one object created, with all the fields from LoggingWidget and also all the fields from Widget. It's not like it creates an instance of LoggingWidget that refers to an instance of Widget.
There's only one object, and therefore only one lock, wherever you synchronize on it.
Related
Which locks are held in overridden non-static synchronized methods.
Please provide the sequence in which the monitor locks of base-class and sub-class are acquired and released so that it explains the benefit of Reentrancy in java. It would be great if the sequences can be explained with the help of owning thread and acquisition count that JVM maintains to implement reentrancy.
public class Widget {
public synchronized void doSomething() {
}
}
public class LoggingWidget extends Widget {
public synchronized void doSomething() {
super.doSomething();
}
}
Please note that this question is specifically asked for the explanation of implicit reentrant locks, so pls dont mark it as a duplicate.
Each object has an associated monitor. When a synchronized instance method is called on an object, the monitor associated with this object needs to be held by the calling thread.
The class of the object is irrelevant.
I understand that Java instance synchronized methods can run parallel and the static ones will serialize the methods; my lack of understanding is, since the static method locks the Class object, what happens with other Class objects; are we locking between all static classes?
thanks.
Instead of taking the lock on the instance/object you are taking it on the class it self.
When you lock the class you are only locking that class, not all classes.
From the docs
A synchronized method acquires a monitor (§17.1) before it executes.
For a class (static) method, the monitor associated with the Class object for the method's class is used.
For an instance method, the monitor associated with this (the object for which the method was invoked) is used.
Java classes have a monitor associated with the class instance. Since there is only one class instance per class the lock will only be acquired on that class instance.
Now each class defined has its own instance and thus its own monitor, so to answer your question: Synchronizing a static method will only block access to that class.
I'm facing an issue regarding Java method synchronization. Let's hope I can explain it briefly:
I have two different methods in two different classes, in two different packages. Something like:
Package1
|_Class1
\MethodA
Package2
|_Class2
\MethodB
Ok, so now I need to synchronize these two methods, which are not threads. So far, I have two different approaches:
Shared semaphore.
Create a shared static semaphore outside Package1 and Package2, something like:
package Package3;
public class SemaphoreClass {
public static Semaphore;
}
I don't really know if JVM would consider this a shared semaphore, anyway.
Synchronized (SharedClass.class).
Using a shared class to synchronize those two methods, something like:
public void MethodA() {
synchronized (SharedClass.class) {
//...
}
and
public void MethodB() {
synchronized (SharedClass.class) {
//...
}
Anyway, these are just approaches. I would like to hear what's the best way to implement what I'm trying to achieve. Having a shared semaphore for JVM would make things easier, but well, I know there must be a solution for this. Thanks in advance.
Both of your approaches should work, but I don't think locking on class is a recommended practices. Prefer locking on instances of Object, or use proper locks from java.util. Also, do not lock on String.
Alternatively, you could let instances of classes Class1 and Class2 can take a lock as parameter during instantiation:
class Class1 {
private final Object lock;
public Class1( Object lock ) { this.lock = lock }
public method() { synchronize( lock ) { } );
}
Then make sure that you create one lock (with new Object()) and pass it to the two instances of Class1 and Class2.
So basically, you've broken down the original problem in two: 1) the two classes do no share anything statically global, they just receive a parameter. 2) the clients of Class1 and Class2 must pass the correct lock. The client of Class1 and Class2 acts as the "orchestrator".
I was reading a thread from CodeRanch saying that abstract methods could not be synchronized due to the fact that an abstract class cannot be instantiated, meaning no object to lock.
This doesn't make sense since an abstract class is a definition (contract) for a child class. The abstract definition of a synchronized method does not need to lock, the child does. All the abstract heading would indicate is that the child must synchronize this method. Is my logic on this correct? If not can someone explain why I'm wrong?
The comment about not being able to instantiate the abstract class is garbage. Given that it has to be an instance method to be abstract, there certainly is a reference which could be locked on. Concrete methods in abstract classes can still refer to this. However, that still doesn't mean that abstract classes should be able to be synchronized.
Whether or not a method is synchronized is an implementation detail of the method. Synchronization isn't specified anywhere as a declarative contract - it's not like you can synchronize in interfaces, either.
How a class implements whatever thread safety guarantees it provides is up to it. If an abstract class wants to mandate a particular approach, it should use the template method pattern:
// I hate synchronizing on "this"
private final Object lock = new Object();
public final void foo() {
synchronized(lock) {
fooImpl();
}
}
protected abstract void fooImpl();
That's pretty dangerous in itself though, given that it's effectively calling "unknown" code within a lock, which is a recipe for deadlocks etc.
Locking behavior shouldn't be specified using abstract methods or interface methods because it shouldn't be part of the contract.
Probably the idea was that locking behavior is fundamentally part of the implementation -- different implementations will want to perform locking differently -- and it would be counterproductive to specify it at that level of abstraction.
Remember the keyword synchronized is specifically for implementing implicit locking (acquiring the lock on the object that the instance method is called on), and there are ways to do locking using alternatives like ReentrantLock, where that keyword is not applicable, or possibly to use CAS or otherwise avoid locking altogether.
synchronized void foo()
{
body
}
is defined to be equivalent to
void foo()
{
synchronized(this)
{
body
}
}
(if static, synchronized on the class instead of this)
Since an abstract method has no body, synchronized keyword on the method is undefined.
I think one logic behind that could be that whether or not to synchronize that method should be decided by the implementing class. Meaning, it gives the freedom to the implementer to choose on whether to provide a synchronized or unsynchronized implementation. Plus, the client would also have option to to select the unsynchronized version so as to avoid synchronization overhead if thread-safety is not an issue.
I'm creating a static class which is going to hold some vectors with info.
I have to make it synchronized so that the class will be locked if someone is editing or reading from the vectors.
What is the best way to do this?
Is it enough to have a function which is synchronized inside the class like this:
public synchronized insertIntoVector(int id)
{
}
Thanks in advance :)
Firstly, you need to define exactly what you mean by "static class". At first, I thought you meant a class where all methods were static (that wasn't meant to be instantiated) - but your code snippet implies this isn't the case.
In any case, synchronized methods inside the class are equivalent to synchronized(this) if they are instance methods, or synchronized(TheContainingClassName.class) if they're static methods.
If you are either creating a non-instantiable class with all static methods, or if you are creating a class that will act as a singleton, then synchronizing every method of the class will ensure that only one thread can be calling methods at once.
Do try to ensure that your methods are atomic though, if possible; calls to different methods can be interleaved by other threads, so something like a getFoo() call followed by a setFoo() (perhaps after incrementing the foo variable) may not have the desired effect if another thread called setFoo() inbetween. The best approach would be to have a method such as incrementFoo(); alternatively (if this is not possible) you can publish the synchronization details so that your callers can manually hold a lock over the class/instance during the entire sequence of calls.
AFAIK, there's no such thing as "static class" in Java. Do you mean a class that contains only static methods? If so, then
public static synchronized void insertIntoVector(int id) {
}
synchronizes with respect to the class object, which is sufficient, if there are only static methods and all of them are synchronized.
If you mean static inner class (where the word "static" has a different meaning than in static methods), then
public synchronized void insertIntoVector(int id)
{
}
synchronizes with respect to an instance of that static inner class.