Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"synchronized(this)" vs. "synchronized((BaseClass)this)" in Java?

This is a successor of my previous question, Is this variable being safely accessed by using synchronization?

For the following program,

Class SubClassB extends SuperClassA {
     protected int c;

     public void inc() {
          synchronized (this) {
               c++;
          }
     }

     public void dec() {
          synchronized ( (SuperClassA) this) {
               c--;
          }
     }
}

Would the counter "c" be accessed thread safe ? I am not sure that in the "dec()" method, is the SuperClassA cast "this" reference a valid object for the synchronized block ? If yes, would the two synchronized blocks lock the same "this" object ? (As it seems to me that "(SuperClassA) this" is not equal to "this")

This strange simulated code comes from the following real life example where SuperClassA is a base class that is not supposed to be modified,

Class SuperClassA {
     protected int c;

     public void dec() {
          synchronized (this) {
               c--;
          }
     }
}

Class SubClassB extends SuperClassA {

     public void inc() {
          synchronized (this) {
               c++;
          }
     }

     public void dec() {
          super.dec();
     }
}

In this example, the "dec()" method in SubClassB calls its superclass's "dec()" method which performs a lock to a "this" object that I suppose to be "SuperClassA.this". If the locked object in SubClassB's "inc()" method is not exactly the same as the locked object in SubClassB's "dec()" method, then I am wondering the inherited counter "c" in SubClassB may NOT be safely accessed by different threads. I feel that there is some ambiguities in using the "this" reference in synchronized blocks.

In the real life example, if I want SubClassB's counter "c" to be thread safe, do I need to add one more synchronized block in its "dec()" method, like this,

Class SubClassB extends SuperClassA {

     public void inc() {
          synchronized (this) {
               c++;
          }
     }

     public void dec() {
          synchronized (this) {
               super.dec();
          }
     }
}

But it seems that such added block is not elegant and may be redundant !

Does anyone have some ideas on these questions. Thanks in advance.

Lawrence

like image 902
user1129812 Avatar asked Jan 05 '12 14:01

user1129812


People also ask

What is the difference between synchronized method and synchronized block?

Synchronized blocks provide granular control over a lock, as you can use arbitrary any lock to provide mutual exclusion to critical section code. On the other hand, the synchronized method always locks either on the current object represented by this keyword or class level lock, if it's a static synchronized method.

Is synchronized block more efficient than synchronized method?

A Java synchronized block doesn't allow more than one JVM, to provide access control to a shared resource. The system performance may degrade because of the slower working of synchronized keyword. Java synchronized block is more efficient than Java synchronized method.

What is synchronization explain synchronized method and synchronized blocks?

synchronized method acquires a lock on the whole object. This means no other thread can use any synchronized method in the whole object while the method is being run by one thread. synchronized blocks acquires a lock in the object between parentheses after the synchronized keyword.

Does synchronized block thread?

Method Synchronization Synchronized methods enables a simple strategy for preventing the thread interference and memory consistency errors. If a Object is visible to more than one threads, all reads or writes to that Object's fields are done through the synchronized method.


2 Answers

The code is thread-safe, because (SomeObject) this adn this are the same object. A cast doesn't transform an object into another object.

The code lacks encapsulation, though, because it lets any subclass access the protected c field in an unsynchronized way. So, any subclass might use c++ or c-- without any synchronization. The field should be private.

like image 198
JB Nizet Avatar answered Oct 03 '22 14:10

JB Nizet


Would the counter "c" be accessed thread safe ?

Yes, it's using the same lock object.

I am not sure that in the "dec()" method, is the SuperClassA cast "this" reference a valid object for the synchronized block ?

Yes.

If yes, would the two synchronized blocks lock the same "this" object ? (As it seems to me that "(SuperClassA) this" is not equal to "this")

Yes. Even if you cast the instance to something it can be casted to (even Object), it'll still refer to the same object.

[...] But it seems that such added block is not elegant and may be redundant !

It is redundant. Extra synchronization is required only if you call multiple synchronized methods and the combined effect must be atomic.

like image 30
David Lantos Avatar answered Oct 03 '22 13:10

David Lantos