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

 

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

  3068人阅读  评论(0)  收藏  举报
  分类:

目录(?)[+]

同步代码块:

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. package threads.ex1;  
  2.   
  3. class KitchenSync {  
  4.     private int[] intArray = new int[10];  
  5.   
  6.     void reverseOrder() {  
  7.         synchronized (this) {  
  8.             int halfWay = intArray.length / 2;  
  9.             for (int i = 0; i < halfWay; ++i) {  
  10.                 int upperIndex = intArray.length - 1 - i;  
  11.                 int save = intArray[upperIndex];  
  12.                 intArray[upperIndex] = intArray[i];  
  13.                 intArray[i] = save;  
  14.             }  
  15.         }  
  16.     }  
  17. }  


反编译后的字节码:

[plain]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. E:\Java\code\jvm\bin\threads\ex1>javap -verbose KitchenSync  
  2. Compiled from "KitchenSync.java"  
  3. class threads.ex1.KitchenSync extends java.lang.Object  
  4.   SourceFile: "KitchenSync.java"  
  5.   minor version: 0  
  6.   major version: 50  
  7.   Constant pool:  
  8. const #1 = class        #2;     //  threads/ex1/KitchenSync  
  9. const #2 = Asciz        threads/ex1/KitchenSync;  
  10. const #3 = class        #4;     //  java/lang/Object  
  11. const #4 = Asciz        java/lang/Object;  
  12. const #5 = Asciz        intArray;  
  13. const #6 = Asciz        [I;  
  14. const #7 = Asciz        <init>;  
  15. const #8 = Asciz        ()V;  
  16. const #9 = Asciz        Code;  
  17. const #10 = Method      #3.#11; //  java/lang/Object."<init>":()V  
  18. const #11 = NameAndType #7:#8;//  "<init>":()V  
  19. const #12 = Field       #1.#13; //  threads/ex1/KitchenSync.intArray:[I  
  20. const #13 = NameAndType #5:#6;//  intArray:[I  
  21. const #14 = Asciz       LineNumberTable;  
  22. const #15 = Asciz       LocalVariableTable;  
  23. const #16 = Asciz       this;  
  24. const #17 = Asciz       Lthreads/ex1/KitchenSync;;  
  25. const #18 = Asciz       reverseOrder;  
  26. const #19 = Asciz       halfWay;  
  27. const #20 = Asciz       I;  
  28. const #21 = Asciz       i;  
  29. const #22 = Asciz       upperIndex;  
  30. const #23 = Asciz       save;  
  31. const #24 = Asciz       StackMapTable;  
  32. const #25 = class       #26;    //  java/lang/Throwable  
  33. const #26 = Asciz       java/lang/Throwable;  
  34. const #27 = Asciz       SourceFile;  
  35. const #28 = Asciz       KitchenSync.java;  
  36.   
  37. {  
  38. threads.ex1.KitchenSync();  
  39.   Code:  
  40.    Stack=2, Locals=1, Args_size=1  
  41.    0:   aload_0  
  42.    1:   invokespecial   #10; //Method java/lang/Object."<init>":()V  
  43.    4:   aload_0  
  44.    5:   bipush  10  
  45.    7:   newarray int  
  46.    9:   putfield        #12; //Field intArray:[I  
  47.    12:  return  
  48.   LineNumberTable:  
  49.    line 3: 0  
  50.    line 4: 4  
  51.    line 3: 12  
  52.   
  53.   LocalVariableTable:  
  54.    Start  Length  Slot  Name   Signature  
  55.    0      13      0    this       Lthreads/ex1/KitchenSync;  
  56.   
  57.   
  58. void reverseOrder();  
  59.   Code:  
  60.    Stack=4, Locals=6, Args_size=1  
  61.    0:   aload_0  
  62.    1:   dup  
  63.    2:   astore_1  
  64.    3:   monitorenter  
  65.    4:   aload_0  
  66.    5:   getfield        #12; //Field intArray:[I  
  67.    8:   arraylength  
  68.    9:   iconst_2  
  69.    10:  idiv  
  70.    11:  istore_2  
  71.    12:  iconst_0  
  72.    13:  istore_3  
  73.    14:  goto    61  
  74.    17:  aload_0  
  75.    18:  getfield        #12; //Field intArray:[I  
  76.    21:  arraylength  
  77.    22:  iconst_1  
  78.    23:  isub  
  79.    24:  iload_3  
  80.    25:  isub  
  81.    26:  istore  4  
  82.    28:  aload_0  
  83.    29:  getfield        #12; //Field intArray:[I  
  84.    32:  iload   4  
  85.    34:  iaload  
  86.    35:  istore  5  
  87.    37:  aload_0  
  88.    38:  getfield        #12; //Field intArray:[I  
  89.    41:  iload   4  
  90.    43:  aload_0  
  91.    44:  getfield        #12; //Field intArray:[I  
  92.    47:  iload_3  
  93.    48:  iaload  
  94.    49:  iastore  
  95.    50:  aload_0  
  96.    51:  getfield        #12; //Field intArray:[I  
  97.    54:  iload_3  
  98.    55:  iload   5  
  99.    57:  iastore  
  100.    58:  iinc    3, 1  
  101.    61:  iload_3  
  102.    62:  iload_2  
  103.    63:  if_icmplt       17  
  104.    66:  aload_1  
  105.    67:  monitorexit  
  106.    68:  goto    74  
  107.    71:  aload_1  
  108.    72:  monitorexit  
  109.    73:  athrow  
  110.    74:  return  
  111.   Exception table:  
  112.    from   to  target type  
  113.      4    68    71   any  
  114.     71    73    71   any  
  115.   LineNumberTable:  
  116.    line 7: 0  
  117.    line 8: 4  
  118.    line 9: 12  
  119.    line 10: 17  
  120.    line 11: 28  
  121.    line 12: 37  
  122.    line 13: 50  
  123.    line 9: 58  
  124.    line 7: 66  
  125.    line 16: 74  
  126.   
  127.   LocalVariableTable:  
  128.    Start  Length  Slot  Name   Signature  
  129.    0      75      0    this       Lthreads/ex1/KitchenSync;  
  130.    12      54      2    halfWay       I  
  131.    14      52      3    i       I  
  132.    28      30      4    upperIndex       I  
  133.    37      21      5    save       I  
  134.   
  135.   StackMapTable: number_of_entries = 4  
  136.    frame_type = 254 /* append */  
  137.      offset_delta = 17  
  138.      locals = [ class threads/ex1/KitchenSync, int, int ]  
  139.    frame_type = 43 /* same */  
  140.    frame_type = 255 /* full_frame */  
  141.      offset_delta = 9  
  142.      locals = [ class threads/ex1/KitchenSync, class threads/ex1/KitchenSync ]  
  143.      stack = [ class java/lang/Throwable ]  
  144.    frame_type = 250 /* chop */  
  145.      offset_delta = 2  
  146.   
  147.   
  148. }  

分析

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

monitorenterc2 objectref →enter monitor for object ("grab the lock" - start of synchronized() section)
monitorexitc3 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 在CODE上查看代码片 派生到我的代码片
  1. package threads.ex1;  
  2.   
  3. class HeatSync {  
  4.     private int[] intArray = new int[10];  
  5.   
  6.     synchronized void reverseOrder() {  
  7.         int halfWay = intArray.length / 2;  
  8.         for (int i = 0; i < halfWay; ++i) {  
  9.             int upperIndex = intArray.length - 1 - i;  
  10.             int save = intArray[upperIndex];  
  11.             intArray[upperIndex] = intArray[i];  
  12.             intArray[i] = save;  
  13.         }  
  14.     }  
  15. }  

反编译后的字节码:

[plain]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. E:\Java\code\jvm\bin\threads\ex1>javap -verbose HeatSync  
  2. Compiled from "HeatSync.java"  
  3. class threads.ex1.HeatSync extends java.lang.Object  
  4.   SourceFile: "HeatSync.java"  
  5.   minor version: 0  
  6.   major version: 50  
  7.   Constant pool:  
  8. const #1 = class        #2;     //  threads/ex1/HeatSync  
  9. const #2 = Asciz        threads/ex1/HeatSync;  
  10. const #3 = class        #4;     //  java/lang/Object  
  11. const #4 = Asciz        java/lang/Object;  
  12. const #5 = Asciz        intArray;  
  13. const #6 = Asciz        [I;  
  14. const #7 = Asciz        <init>;  
  15. const #8 = Asciz        ()V;  
  16. const #9 = Asciz        Code;  
  17. const #10 = Method      #3.#11; //  java/lang/Object."<init>":()V  
  18. const #11 = NameAndType #7:#8;//  "<init>":()V  
  19. const #12 = Field       #1.#13; //  threads/ex1/HeatSync.intArray:[I  
  20. const #13 = NameAndType #5:#6;//  intArray:[I  
  21. const #14 = Asciz       LineNumberTable;  
  22. const #15 = Asciz       LocalVariableTable;  
  23. const #16 = Asciz       this;  
  24. const #17 = Asciz       Lthreads/ex1/HeatSync;;  
  25. const #18 = Asciz       reverseOrder;  
  26. const #19 = Asciz       halfWay;  
  27. const #20 = Asciz       I;  
  28. const #21 = Asciz       i;  
  29. const #22 = Asciz       upperIndex;  
  30. const #23 = Asciz       save;  
  31. const #24 = Asciz       StackMapTable;  
  32. const #25 = Asciz       SourceFile;  
  33. const #26 = Asciz       HeatSync.java;  
  34.   
  35. {  
  36. threads.ex1.HeatSync();  
  37.   Code:  
  38.    Stack=2, Locals=1, Args_size=1  
  39.    0:   aload_0  
  40.    1:   invokespecial   #10; //Method java/lang/Object."<init>":()V  
  41.    4:   aload_0  
  42.    5:   bipush  10  
  43.    7:   newarray int  
  44.    9:   putfield        #12; //Field intArray:[I  
  45.    12:  return  
  46.   LineNumberTable:  
  47.    line 3: 0  
  48.    line 4: 4  
  49.    line 3: 12  
  50.   
  51.   LocalVariableTable:  
  52.    Start  Length  Slot  Name   Signature  
  53.    0      13      0    this       Lthreads/ex1/HeatSync;  
  54.   
  55.   
  56. synchronized void reverseOrder();  
  57.   Code:  
  58.    Stack=4, Locals=5, Args_size=1  
  59.    0:   aload_0  
  60.    1:   getfield        #12; //Field intArray:[I  
  61.    4:   arraylength  
  62.    5:   iconst_2  
  63.    6:   idiv  
  64.    7:   istore_1  
  65.    8:   iconst_0  
  66.    9:   istore_2  
  67.    10:  goto    54  
  68.    13:  aload_0  
  69.    14:  getfield        #12; //Field intArray:[I  
  70.    17:  arraylength  
  71.    18:  iconst_1  
  72.    19:  isub  
  73.    20:  iload_2  
  74.    21:  isub  
  75.    22:  istore_3  
  76.    23:  aload_0  
  77.    24:  getfield        #12; //Field intArray:[I  
  78.    27:  iload_3  
  79.    28:  iaload  
  80.    29:  istore  4  
  81.    31:  aload_0  
  82.    32:  getfield        #12; //Field intArray:[I  
  83.    35:  iload_3  
  84.    36:  aload_0  
  85.    37:  getfield        #12; //Field intArray:[I  
  86.    40:  iload_2  
  87.    41:  iaload  
  88.    42:  iastore  
  89.    43:  aload_0  
  90.    44:  getfield        #12; //Field intArray:[I  
  91.    47:  iload_2  
  92.    48:  iload   4  
  93.    50:  iastore  
  94.    51:  iinc    2, 1  
  95.    54:  iload_2  
  96.    55:  iload_1  
  97.    56:  if_icmplt       13  
  98.    59:  return  
  99.   LineNumberTable:  
  100.    line 7: 0  
  101.    line 8: 8  
  102.    line 9: 13  
  103.    line 10: 23  
  104.    line 11: 31  
  105.    line 12: 43  
  106.    line 8: 51  
  107.    line 14: 59  
  108.   
  109.   LocalVariableTable:  
  110.    Start  Length  Slot  Name   Signature  
  111.    0      60      0    this       Lthreads/ex1/HeatSync;  
  112.    8      52      1    halfWay       I  
  113.    10      49      2    i       I  
  114.    23      28      3    upperIndex       I  
  115.    31      20      4    save       I  
  116.   
  117.   StackMapTable: number_of_entries = 2  
  118.    frame_type = 253 /* append */  
  119.      offset_delta = 13  
  120.      locals = [ int, int ]  
  121.    frame_type = 40 /* same */  
  122.   
  123.   
  124. }  

分析

可以看到,同步方法没有使用monitorenter和monitorexit这两个指令。

方法return后也没有Exception table。

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


总结

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

0
0
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值