How synchronized keyword behaves in methods. I’ve heard speculation that doFoo1() would result into more compact byte code, but I don’t buy that.

Assumption:
Byte code in both cases, is same.

So we have this sample,

[code lang=”java”]
class SyncMe {

synchronized void doFoo1() {
int x = 0;
}

void doFoo2() {
synchronized (this) {
int x = 0;
}
}
}
[/code]

And the result is, javap -c SyncMe

[code lang=”java”]
class SyncMe {
SyncMe();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object.””:()V
4: return

synchronized void doFoo1();
Code:
0: iconst_0
1: istore_1
2: return

void doFoo2();
Code:
0: aload_0
1: dup
2: astore_1
3: monitorenter
4: iconst_0
5: istore_2
6: aload_1
7: monitorexit
8: goto 16
11: astore_3
12: aload_1
13: monitorexit
14: aload_3
15: athrow
16: return
Exception table:
from to target type
4 8 11 any
11 14 11 any
}
[/code]

Result:
Howly cotton ball. They really ARE different. Based on this is more adviceable to use synchronized keyword in method, than adding blocks manually inside the method.

TIP:
So how you do that, in practise. Answer is simple, use good approach of using small methods.

[code lang=”java”]
class SyncProper {
int x;

synchronized void resetX() {
x = 0;
}

void doGood() {
// do stuff
resetX();
// do more stuff
}

void doBad() {
// do stuff
synchronized (this) {
x = 0;
}
// do more stuff
}
}
[/code]

And as simple as that, simple and clean code, relying good programming patterns, leads into best optimized code.

[code lang=”java”]
class SyncProper {
int x;

SyncProper();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object.””:()V
4: return

synchronized void resetX();
Code:
0: aload_0
1: iconst_0
2: putfield #2 // Field x:I
5: return

void doGood();
Code:
0: aload_0
1: invokevirtual #3 // Method resetX:()V
4: return

void doBad();
Code:
0: aload_0
1: dup
2: astore_1
3: monitorenter
4: aload_0
5: iconst_0
6: putfield #2 // Field x:I
9: aload_1
10: monitorexit
11: goto 19
14: astore_2
15: aload_1
16: monitorexit
17: aload_2
18: athrow
19: return
Exception table:
from to target type
4 11 14 any
14 17 14 any
}
[/code]

As class file size, doing it good way, resulted into class file of size 344 bytes, and using bad way resulted 390 bytes. Naturally those were measure by using exactly same length class/field/method names to avoid variance due to that. Notice, however, that good way has one extra method (resetX()), but it still manages to be much smaller. Do you still need more proof to prefer small maintainable methods? If you code in the manner what JVM likes, you will make code more clean, and very likely also faster, since, for example, in this case code for managing synchronized is externalized into native code (well, I’m guessing here) or at least closer to JIT/JVM machine.

So follow da-leader, and doGood(). Don’t speculate, trust the results.

References:
Stackoverlow: What is the difference between synchronized(this) and synchronized method
Stackoverflow: synchronized block vs synchronized method?
IBM developerWorks: Java bytecode: Understanding bytecode makes you a better programmer
Code Impossible: Java Bytecode Fundamentals

/ java

Vastaa

Sähköpostiosoitettasi ei julkaista. Pakolliset kentät on merkitty *

This site uses Akismet to reduce spam. Learn how your comment data is processed.