您的位置:首页 > 编程语言 > Java开发

java同步方法和同步代码块的区别

2016-01-24 19:07 686 查看


java同步方法和同步代码块的区别

2014-03-25 21:13 3068人阅读 评论(0) 收藏 举报


分类:

java(120)


版权声明:本文为博主原创文章,未经博主允许不得转载。

目录(?)[+]

同步代码块:

[java] view
plaincopy





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
plaincopy





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 <init>;

const #8 = Asciz ()V;

const #9 = Asciz Code;

const #10 = Method #3.#11; // java/lang/Object."<init>":()V

const #11 = NameAndType #7:#8;// "<init>":()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."<init>":()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





}

分析

方法内的同步语句会使用两个指令:

monitorenterc2objectref →enter monitor for object ("grab the lock" - start of synchronized() section)
monitorexitc3objectref →exit monitor for object ("release the lock" - end of synchronized() section)
当java虚拟机遇到monitorenter的时候,它获得栈中objectref所引用的对象的锁。如果线程已经拥有了那个对象的锁,锁的计数器会加1。线程中每条monitorexit指令都会引起计数器减1。当计数器变成0的时候,监视器就释放了。

而且return后,还有Exception table。

同步方法:

[java] view
plaincopy





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
plaincopy





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 <init>;

const #8 = Asciz ()V;

const #9 = Asciz Code;

const #10 = Method #3.#11; // java/lang/Object."<init>":()V

const #11 = NameAndType #7:#8;// "<init>":()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."<init>":()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。

当虚拟机解析对方法的符号引用时,它判断这个方法是否是同步的。如果是同步的,虚拟机就在调用方法之前获取一个锁。

总结

因此,同步方法比同步代码块更高效,但是它们的功能是一样的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: