Are the following classes equivalent in Java? if no, why?
class Abc { private int c = 0;
} } class Def { private int c = 0; private final Object lock = new Object();public synchronized void add(int a) { c += a; } public synchronized void subtract(int a) { c -= a;
} }public void add(int a) { synchronized(lock) { c += a; } } public void subtract(int a) { synchronized(lock) { c -= a; }
Also, what would be the problem of in
Def
, usingthis
as synchronized parameter instead oflock
? Is the following the problem?Def def = new Def() synchronized (def) { def.add(5); //originates deadlock? or is this allowed AS LONG //as all this happens in the same thread? }
Are synchronized statements in Java just like C#'s lock statements? If no, what are their differences? If yes, why doesn't C# also allow to lock the methods, like Java allows?
So I guess the problem with
synchronized (this)
can be depicted by the following example?class Xyz { private int c;
}public void add(int a) { synchronized(this) { c += a; } } public void subtract(int a) { synchronized(this) { c -= a; } } public void show666() { return 666; }
Thread1 calls
xyz.add(0)
and at the same time Thread2 tries to callxyz.show666()
. Thread2 has to wait for Thread1 to finish withxyz.add(0)
althtough it doesn't need any info directly related with the lock. Is that it?

- 101,373
- 131
- 340
- 557
5 Answers
No they are different. using
synchronized(reference){}
obtains the monitor lock on the given reference (your lock object) and usingsynchronized
in a method declaration usesthis
for the monitor lock. The net result is that an exteral caller can't obtain the same lock as theadd
andsubtract
methods.There won't be a deadlock, you can hold any number of monitor locks, plus the
Def
object uses a different object to lock on. But even if it was the first classAbc
it won't deadlock. Synchronized locks in java are reetrant. So you can in theory attempt to lock them on the same thread as many times as you like.It's surprising that C# doesn't allow
lock
to be used on methods, but it does seem to be similar if not identical to the javasynchronized
keyword when used on a reference. One of the design goals of C# was to be familar enough for Java developers to be able to pick it up with out have there minds completely replaced, so I guess this isn't too surprising.

- 27,701
- 12
- 73
- 106
-
changing the synchronized (lock) to synchronized(this) would make them equivalent? – devoured elysium Jan 04 '11 at 09:04
1 Are the following classes equivalent in Java? if no, why?
They differ by what instance they synchronize on and thus are affected by the differences between those instances.
Class Abc
uses the Abc
instance that the method is being invoked upon. Other code with access to the instance can use it to synchronize as well by explicitly using the instance in a synchronized block.
The synchronize code blocks in Class Def
explicitly name the instance they synchronizes with. Since this instance is private to the Def
instance, code external to Def
cannot use it to synchronize (unless the instance is somehow leaked).
Some may argue that the Def
approach is much safer, that it is important to encapsulate your locks for the same reason you should use private instance variables.
Finally, there are the differences between the synchronized keyword and using the synchronized statement, e.g. the synchronized statement can lock on any object, not just the instance of the executing code, the synchronize keyword is slightly more efficient, etc.
2a Also, what would be the problem of in Def, using this as synchronized parameter instead of lock?
No problem. Using synchronized keyword on an instance method is semantically identical to wrapping the code of the method in a synchronized block synchronized on this
(the synchronized keyword is slightly more efficient). Using the synchronized keyword on a static method is the same as using a synchronized block synchronized on the class itself (e.g. synchronized(FooBar.class) { ... }
).
2b Is the following the problem?
No, locks in Java are reentrant, which just means that the thread holding the lock on the protecting instance can enter and exit any other code block synchronized on the same instance.
3a Are synchronized statements in Java just like C#'s lock statements? If no, what are their differences?
Semantically equivalent.
But note this answer about Monitor.Enter
and Monitor.Exit
Are there any differences between Java's "synchronized" and C#'s "lock"?
3b If yes, why doesn't C# also allow to lock the methods, like Java allows?
It does - use the [MethodImpl(MethodImplOptions.Synchronized)]
annotation.
4 Thread1 calls xyz.add(0) and at the same time Thread2 tries to call xyz.show666(). Thread2 has to wait for Thread1 to finish with xyz.add(0) althtough it doesn't need any info directly related with the lock. Is that it?
No, a lot of people assume "locking" an instance affects the entire instance. It only affects synchronized code (synchronized methods and code within a synchronized statement) that is synchronized on that instance. Unsynchronized code is unaffected (at least until it hits a synchronized statement or calls a synchronized method).
The unsynchronized method show666()
won't cause the thread to block. Nothing changes if the synchronized(this)
statements were changed into synchronized
methods - again show666
won't block (unless its synchronized too).
They are almost equivalent, with one little difference: since
Def
uses an internal private object as lock, noone else can lock on that object from the outside world. In case of theAbc
object, it is possible that someone else locks on the object then calls some of its methods from a different thread, which may result in deadlock. The practical possibility of this is faint (as it clearly requires some mischief or ignorance on another programmer's behalf), but is not zero. Therefore some people prefer theDef
style to be on the safe side, although AFAIK the common idiom is as inAbc
.Java locks are reentrant, so invoking a lock multiple times from the same thread is OK.
Sorry, I am not competent on C#.
Did you mean
synchronized(this)
instead ofsynchronized(lock)
in the code example? Anyway, sinceshow666
is not synchronized, calls to it do not block, even if another call to a synhronized method blocks on the same object.

- 114,404
- 31
- 268
- 329
-
1. so if Def had defined synchronized(this) instead of synchronized(lock) they would be equivalent? – devoured elysium Jan 04 '11 at 09:03
-
1yes functionally, not sure if the byte code would be exactly the same – Gareth Davis Jan 04 '11 at 09:04
-
thanks. having in mind that java's locks are reentrant, could you tell me in which situation it is a bad thing to do lock(this)? – devoured elysium Jan 04 '11 at 09:06
-
I guess syncronized(this) is only 'bad'(can't say it's really bad) when it could have been replaced with a synchronized keyword on the method.. one set of {} less. Some poeple prefer synchronized(this) as it prevents the details of the locking from leaking out into the public interface of the object a bit of personal preference going on here. – Gareth Davis Jan 04 '11 at 09:14
-
Isn't there any situation where the client of the class not knowing that this class uses locks could lead to a problem? – devoured elysium Jan 04 '11 at 09:21
-
@devoured, surely there is - there can be both concurrency bugs and performance issues. This is why it is important to document the thread safety level and strategy of one's classes in Javadoc. That does not eliminate the risk, but at least alleviates it. – Péter Török Jan 04 '11 at 09:28
-
-
see http://download.oracle.com/javase/tutorial/essential/concurrency/locksync.html
It should help you to answer 1 & 2, in particular it states:
Reentrant Synchronization
Recall that a thread cannot acquire a lock owned by another thread. But a thread can acquire a lock that it already owns. Allowing a thread to acquire the same lock more than once enables reentrant synchronization. This describes a situation where synchronized code, directly or indirectly, invokes a method that also contains synchronized code, and both sets of code use the same lock. Without reentrant synchronization, synchronized code would have to take many additional precautions to avoid having a thread cause itself to block.
From that I understand that unless lock is synchronized by someone else, the two class are pretty much equivalent from the outside.
Should not cause any particular problem thanks to Reentrant synchronization
(3. not familiar with C#)

- 680
- 5
- 11
1.Generally, they are different, since monitors of different objects are used in synchronized modules. BTW, these two classes will behave equivalently, if you will not use monitor of Abc class instances (particularly, if you will not use synchronized(abcObject){} outside abc class, where abcObject is an instance of Abc class)
2.a. The following two methods are equal:
public void add(int a) {
synchronized(this) {
c += a;
}
}
and
public synchronized void add(int a) {
c += a;
}
2.b. I don't see any problem in that code: two monitors (def instance's monitor and def.lock instance's monitor) are always locked in strict order (no circular wait condition)
3.Can't say anything about C#

- 7,680
- 3
- 29
- 39