While discussing a Java synchronization question, someone made a comment that the following snippets are not equivalent (and may compile to different bytecodes):
public synchronized void someMethod() {
//stuff
}
and
public void someMethod() {
synchronized (this) {
//stuff
}
}
Are they equivalent?
Synchronized keyword limitations concurrent. locks package from Java 1.5 introduces a Lock interface defined as an alternative to the synchronized keyword : Lock implementations provide more extensive locking operations than can be obtained using synchronized methods and statements.
Only one thread can execute inside a synchronized instance method.
Synchronized static methods are synchronized on the class object of the class the synchronized static method belongs to. Since only one class object exists in the Java VM per class, only one thread can execute inside a static synchronized method in the same class.
They are equivalent in function, though the compilers I tested (Java 1.6.0_07 and Eclipse 3.4) generate different bytecode. The first generates:
// access flags 33
public synchronized someMethod()V
RETURN
The second generates:
// access flags 1
public someMethod()V
ALOAD 0
DUP
MONITORENTER
MONITOREXIT
RETURN
(Thanks to ASM for the bytecode printing).
So the difference between them persists to the bytecode level, and it's up to the JVM to make their behavior the same. However, they do have the same functional effect - see the example in the Java Language Specification.
It should be noted, that if the method is overridden in a subclass, that it is not necessarily synchronized - so there is no difference in that respect either.
I also ran a test to block a thread trying access the monitor in each case to compare what their stack traces would look like in a thread dump, and they both contained the method in question, so there is no difference there either.
I made the original comment that the statements are identical.
In both cases, the first thing that happens is that the calling thread will try to acquire the current object's (meaning, this
') monitor.
I don't know about different bytecode, I'll be happy to hear the difference. But in practice, they are 100% identical.
EDIT: i'm going to clarify this as some people here got it wrong. Consider:
public class A {
public synchronized void doStuff()
{
// do stuff
}
}
public class B extends A {
public void doStuff()
{
// do stuff
// THIS IS OVERRIDE!
}
}
In this case doStuff()
in class B still overrides doStuff()
in class A even though it is not synchronized.
Synchronized keyword is never part of the contract! Not for subclasses, not for interfaces, not for abstract classes.
I made the original comment. My comment was that they are logically equivalent, but compile to different bytecode.
I didn't add anything else to justify it at the time because there's not much to justify really-- they just do compile to different bytecode. If you declare a method as synchronized, then that synchronization is part of the method's definition. A synchronized block within a method isn't part of the method's definition, but instead involves separate bytecodes to acquire and release the monitor, as one of the posters above has illustrated. Strictly speaking, they're slightly different things, though to the overall logic of your program, they're equivalent.
When does this matter? Well, on most modern desktop VMs, hardly ever. But for example:
Yes. Using the synchronized keyword on an instance method uses 'this' as a monitor ,also using it on a class method (static method) uses the class' Class object (Foo.class).
This way you can synchronize entire methods, and in the same time, synchronize it with a code snippet in another method using the synchronized-block style.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With