多线程---java同步方法和同步代码块的区别

同步代码块:
[java] view plain copy
package threads.ex1;

class KitchenSync {
private int[] intArray = new int[10];

void reverseOrder() {  
    synchronized (this) {  
        int halfWay = intArray.length / 2;  
        for (int i = 0; i < halfWay; ++i) {  
            int upperIndex = intArray.length - 1 - i;  
            int save = intArray[upperIndex];  
            intArray[upperIndex] = intArray[i];  
            intArray[i] = save;  
        }  
    }  
}  

}

反编译后的字节码:
[plain] view plain copy
E:\Java\code\jvm\bin\threads\ex1>javap -verbose KitchenSync
Compiled from “KitchenSync.java”
class threads.ex1.KitchenSync extends java.lang.Object
SourceFile: “KitchenSync.java”
minor version: 0
major version: 50
Constant pool:
const #1 = class #2; // threads/ex1/KitchenSync
const #2 = Asciz threads/ex1/KitchenSync;
const #3 = class #4; // java/lang/Object
const #4 = Asciz java/lang/Object;
const #5 = Asciz intArray;
const #6 = Asciz [I;
const #7 = Asciz ;
const #8 = Asciz ()V;
const #9 = Asciz Code;
const #10 = Method #3.#11; // java/lang/Object.””:()V
const #11 = NameAndType #7:#8;// “”:()V
const #12 = Field #1.#13; // threads/ex1/KitchenSync.intArray:[I
const #13 = NameAndType #5:#6;// intArray:[I
const #14 = Asciz LineNumberTable;
const #15 = Asciz LocalVariableTable;
const #16 = Asciz this;
const #17 = Asciz Lthreads/ex1/KitchenSync;;
const #18 = Asciz reverseOrder;
const #19 = Asciz halfWay;
const #20 = Asciz I;
const #21 = Asciz i;
const #22 = Asciz upperIndex;
const #23 = Asciz save;
const #24 = Asciz StackMapTable;
const #25 = class #26; // java/lang/Throwable
const #26 = Asciz java/lang/Throwable;
const #27 = Asciz SourceFile;
const #28 = Asciz KitchenSync.java;

{
threads.ex1.KitchenSync();
Code:
Stack=2, Locals=1, Args_size=1
0: aload_0
1: invokespecial #10; //Method java/lang/Object.””:()V
4: aload_0
5: bipush 10
7: newarray int
9: putfield #12; //Field intArray:[I
12: return
LineNumberTable:
line 3: 0
line 4: 4
line 3: 12

LocalVariableTable:
Start Length Slot Name Signature
0 13 0 this Lthreads/ex1/KitchenSync;

void reverseOrder();
Code:
Stack=4, Locals=6, Args_size=1
0: aload_0
1: dup
2: astore_1
3: monitorenter
4: aload_0
5: getfield #12; //Field intArray:[I
8: arraylength
9: iconst_2
10: idiv
11: istore_2
12: iconst_0
13: istore_3
14: goto 61
17: aload_0
18: getfield #12; //Field intArray:[I
21: arraylength
22: iconst_1
23: isub
24: iload_3
25: isub
26: istore 4
28: aload_0
29: getfield #12; //Field intArray:[I
32: iload 4
34: iaload
35: istore 5
37: aload_0
38: getfield #12; //Field intArray:[I
41: iload 4
43: aload_0
44: getfield #12; //Field intArray:[I
47: iload_3
48: iaload
49: iastore
50: aload_0
51: getfield #12; //Field intArray:[I
54: iload_3
55: iload 5
57: iastore
58: iinc 3, 1
61: iload_3
62: iload_2
63: if_icmplt 17
66: aload_1
67: monitorexit
68: goto 74
71: aload_1
72: monitorexit
73: athrow
74: return
Exception table:
from to target type
4 68 71 any
71 73 71 any
LineNumberTable:
line 7: 0
line 8: 4
line 9: 12
line 10: 17
line 11: 28
line 12: 37
line 13: 50
line 9: 58
line 7: 66
line 16: 74

LocalVariableTable:
Start Length Slot Name Signature
0 75 0 this Lthreads/ex1/KitchenSync;
12 54 2 halfWay I
14 52 3 i I
28 30 4 upperIndex I
37 21 5 save I

StackMapTable: number_of_entries = 4
frame_type = 254 /* append */
offset_delta = 17
locals = [ class threads/ex1/KitchenSync, int, int ]
frame_type = 43 /* same */
frame_type = 255 /* full_frame */
offset_delta = 9
locals = [ class threads/ex1/KitchenSync, class threads/ex1/KitchenSync ]
stack = [ class java/lang/Throwable ]
frame_type = 250 /* chop */
offset_delta = 2

}

分析
方法内的同步语句会使用两个指令:
monitorenter c2 objectref → enter monitor for object (“grab the lock” - start of synchronized() section)
monitorexit c3 objectref → exit monitor for object (“release the lock” - end of synchronized() section)
当Java虚拟机遇到monitorenter的时候,它获得栈中objectref所引用的对象的锁。如果线程已经拥有了那个对象的锁,锁的计数器会加1。线程中每条monitorexit指令都会引起计数器减1。当计数器变成0的时候,监视器就释放了。
而且return后,还有Exception table。

同步方法:
[java] view plain copy
package threads.ex1;

class HeatSync {
private int[] intArray = new int[10];

synchronized void reverseOrder() {  
    int halfWay = intArray.length / 2;  
    for (int i = 0; i < halfWay; ++i) {  
        int upperIndex = intArray.length - 1 - i;  
        int save = intArray[upperIndex];  
        intArray[upperIndex] = intArray[i];  
        intArray[i] = save;  
    }  
}  

}

反编译后的字节码:
[plain] view plain copy
E:\Java\code\jvm\bin\threads\ex1>javap -verbose HeatSync
Compiled from “HeatSync.java”
class threads.ex1.HeatSync extends java.lang.Object
SourceFile: “HeatSync.java”
minor version: 0
major version: 50
Constant pool:
const #1 = class #2; // threads/ex1/HeatSync
const #2 = Asciz threads/ex1/HeatSync;
const #3 = class #4; // java/lang/Object
const #4 = Asciz java/lang/Object;
const #5 = Asciz intArray;
const #6 = Asciz [I;
const #7 = Asciz ;
const #8 = Asciz ()V;
const #9 = Asciz Code;
const #10 = Method #3.#11; // java/lang/Object.””:()V
const #11 = NameAndType #7:#8;// “”:()V
const #12 = Field #1.#13; // threads/ex1/HeatSync.intArray:[I
const #13 = NameAndType #5:#6;// intArray:[I
const #14 = Asciz LineNumberTable;
const #15 = Asciz LocalVariableTable;
const #16 = Asciz this;
const #17 = Asciz Lthreads/ex1/HeatSync;;
const #18 = Asciz reverseOrder;
const #19 = Asciz halfWay;
const #20 = Asciz I;
const #21 = Asciz i;
const #22 = Asciz upperIndex;
const #23 = Asciz save;
const #24 = Asciz StackMapTable;
const #25 = Asciz SourceFile;
const #26 = Asciz HeatSync.java;

{
threads.ex1.HeatSync();
Code:
Stack=2, Locals=1, Args_size=1
0: aload_0
1: invokespecial #10; //Method java/lang/Object.””:()V
4: aload_0
5: bipush 10
7: newarray int
9: putfield #12; //Field intArray:[I
12: return
LineNumberTable:
line 3: 0
line 4: 4
line 3: 12

LocalVariableTable:
Start Length Slot Name Signature
0 13 0 this Lthreads/ex1/HeatSync;

synchronized void reverseOrder();
Code:
Stack=4, Locals=5, Args_size=1
0: aload_0
1: getfield #12; //Field intArray:[I
4: arraylength
5: iconst_2
6: idiv
7: istore_1
8: iconst_0
9: istore_2
10: goto 54
13: aload_0
14: getfield #12; //Field intArray:[I
17: arraylength
18: iconst_1
19: isub
20: iload_2
21: isub
22: istore_3
23: aload_0
24: getfield #12; //Field intArray:[I
27: iload_3
28: iaload
29: istore 4
31: aload_0
32: getfield #12; //Field intArray:[I
35: iload_3
36: aload_0
37: getfield #12; //Field intArray:[I
40: iload_2
41: iaload
42: iastore
43: aload_0
44: getfield #12; //Field intArray:[I
47: iload_2
48: iload 4
50: iastore
51: iinc 2, 1
54: iload_2
55: iload_1
56: if_icmplt 13
59: return
LineNumberTable:
line 7: 0
line 8: 8
line 9: 13
line 10: 23
line 11: 31
line 12: 43
line 8: 51
line 14: 59

LocalVariableTable:
Start Length Slot Name Signature
0 60 0 this Lthreads/ex1/HeatSync;
8 52 1 halfWay I
10 49 2 i I
23 28 3 upperIndex I
31 20 4 save I

StackMapTable: number_of_entries = 2
frame_type = 253 /* append */
offset_delta = 13
locals = [ int, int ]
frame_type = 40 /* same */

}

分析
可以看到,同步方法没有使用monitorenter和monitorexit这两个指令。
方法return后也没有Exception table。
当虚拟机解析对方法的符号引用时,它判断这个方法是否是同步的。如果是同步的,虚拟机就在调用方法之前获取一个锁。

总结
因此,同步方法比同步代码块更高效,但是它们的功能是一样的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值