zoukankan      html  css  js  c++  java
  • java中synchronized关键字分析

    今天我们来分析一下java中synchronized关键字。首先来看一段java代码:(本地编译环境为mac,jdk1.8的环境)

    Demo.java

    1 package com.example.springcloud.provider.demo;
    2 
    3 public class Demo {
    4     private boolean isOk = true;
    5 
    6     public void test(){
    7         isOk=false;
    8     }
    9 }

    编译周后的Demo.class二进制文件:

    Demo.class

     1 cafe babe 0000 0034 0015 0a00 0400 1109
     2 0003 0012 0700 1307 0014 0100 0469 734f
     3 6b01 0001 5a01 0006 3c69 6e69 743e 0100
     4 0328 2956 0100 0443 6f64 6501 000f 4c69
     5 6e65 4e75 6d62 6572 5461 626c 6501 0012
     6 4c6f 6361 6c56 6172 6961 626c 6554 6162
     7 6c65 0100 0474 6869 7301 002c 4c63 6f6d
     8 2f65 7861 6d70 6c65 2f73 7072 696e 6763
     9 6c6f 7564 2f70 726f 7669 6465 722f 6465
    10 6d6f 2f44 656d 6f3b 0100 0474 6573 7401
    11 000a 536f 7572 6365 4669 6c65 0100 0944
    12 656d 6f2e 6a61 7661 0c00 0700 080c 0005
    13 0006 0100 2a63 6f6d 2f65 7861 6d70 6c65
    14 2f73 7072 696e 6763 6c6f 7564 2f70 726f
    15 7669 6465 722f 6465 6d6f 2f44 656d 6f01
    16 0010 6a61 7661 2f6c 616e 672f 4f62 6a65
    17 6374 0021 0003 0004 0000 0001 0002 0005
    18 0006 0000 0002 0001 0007 0008 0001 0009
    19 0000 0038 0002 0001 0000 000a 2ab7 0001
    20 2a04 b500 02b1 0000 0002 000a 0000 000a
    21 0002 0000 0003 0004 0004 000b 0000 000c
    22 0001 0000 000a 000c 000d 0000 0001 000e
    23 0008 0001 0009 0000 0034 0002 0001 0000
    24 0006 2a03 b500 02b1 0000 0002 000a 0000
    25 000a 0002 0000 0007 0005 0008 000b 0000
    26 000c 0001 0000 0006 000c 000d 0000 0001
    27 000f 0000 0002 0010 

    使用javap -v Demo.class  > Demo.txt 文件得到反编译的汇编语言:

    Demo.txt

     1 Classfile /Users/shiwen/IdeaProjects/springcloud/example-springcloud-provider/target/classes/com/example/springcloud/provider/demo/Demo.class
     2   Last modified 2017-10-11; size 424 bytes
     3   MD5 checksum 1f57b26a93d1cc466ff58bcec5ff37fb
     4   Compiled from "Demo.java"
     5 public class com.example.springcloud.provider.demo.Demo
     6   minor version: 0
     7   major version: 52
     8   flags: ACC_PUBLIC, ACC_SUPER
     9 Constant pool:
    10    #1 = Methodref          #4.#17         // java/lang/Object."<init>":()V
    11    #2 = Fieldref           #3.#18         // com/example/springcloud/provider/demo/Demo.isOk:Z
    12    #3 = Class              #19            // com/example/springcloud/provider/demo/Demo
    13    #4 = Class              #20            // java/lang/Object
    14    #5 = Utf8               isOk
    15    #6 = Utf8               Z
    16    #7 = Utf8               <init>
    17    #8 = Utf8               ()V
    18    #9 = Utf8               Code
    19   #10 = Utf8               LineNumberTable
    20   #11 = Utf8               LocalVariableTable
    21   #12 = Utf8               this
    22   #13 = Utf8               Lcom/example/springcloud/provider/demo/Demo;
    23   #14 = Utf8               test
    24   #15 = Utf8               SourceFile
    25   #16 = Utf8               Demo.java
    26   #17 = NameAndType        #7:#8          // "<init>":()V
    27   #18 = NameAndType        #5:#6          // isOk:Z
    28   #19 = Utf8               com/example/springcloud/provider/demo/Demo
    29   #20 = Utf8               java/lang/Object
    30 {
    31   public com.example.springcloud.provider.demo.Demo();
    32     descriptor: ()V
    33     flags: ACC_PUBLIC
    34     Code:
    35       stack=2, locals=1, args_size=1
    36          0: aload_0
    37          1: invokespecial #1                  // Method java/lang/Object."<init>":()V
    38          4: aload_0
    39          5: iconst_1
    40          6: putfield      #2                  // Field isOk:Z
    41          9: return
    42       LineNumberTable:
    43         line 3: 0
    44         line 4: 4
    45       LocalVariableTable:
    46         Start  Length  Slot  Name   Signature
    47             0      10     0  this   Lcom/example/springcloud/provider/demo/Demo;
    48 
    49   public void test();
    50     descriptor: ()V
    51     flags: ACC_PUBLIC
    52     Code:
    53       stack=2, locals=1, args_size=1
    54          0: aload_0
    55          1: iconst_0
    56          2: putfield      #2                  // Field isOk:Z
    57          5: return
    58       LineNumberTable:
    59         line 7: 0
    60         line 8: 5
    61       LocalVariableTable:
    62         Start  Length  Slot  Name   Signature
    63             0       6     0  this   Lcom/example/springcloud/provider/demo/Demo;
    64 }
    65 SourceFile: "Demo.java"

    修改Demo.java文件在方法中新增synchronized如下:

    package com.example.springcloud.provider.demo;
    
    public class Demo {
        private boolean isOk = true;
    
        private synchronized void test(){
        isOk=false;
    } }

    反编译为汇编后:(不同的地方用黄色标识出来了)

     1 Classfile /Users/shiwen/IdeaProjects/springcloud/example-springcloud-provider/target/classes/com/example/springcloud/provider/demo/Demo.class
     2   Last modified 2017-10-11; size 424 bytes
     3   MD5 checksum 000d5f4eb139b3d12c483f7087c0c970
     4   Compiled from "Demo.java"
     5 public class com.example.springcloud.provider.demo.Demo
     6   minor version: 0
     7   major version: 52
     8   flags: ACC_PUBLIC, ACC_SUPER
     9 Constant pool:
    10    #1 = Methodref          #4.#17         // java/lang/Object."<init>":()V
    11    #2 = Fieldref           #3.#18         // com/example/springcloud/provider/demo/Demo.isOk:Z
    12    #3 = Class              #19            // com/example/springcloud/provider/demo/Demo
    13    #4 = Class              #20            // java/lang/Object
    14    #5 = Utf8               isOk
    15    #6 = Utf8               Z
    16    #7 = Utf8               <init>
    17    #8 = Utf8               ()V
    18    #9 = Utf8               Code
    19   #10 = Utf8               LineNumberTable
    20   #11 = Utf8               LocalVariableTable
    21   #12 = Utf8               this
    22   #13 = Utf8               Lcom/example/springcloud/provider/demo/Demo;
    23   #14 = Utf8               test
    24   #15 = Utf8               SourceFile
    25   #16 = Utf8               Demo.java
    26   #17 = NameAndType        #7:#8          // "<init>":()V
    27   #18 = NameAndType        #5:#6          // isOk:Z
    28   #19 = Utf8               com/example/springcloud/provider/demo/Demo
    29   #20 = Utf8               java/lang/Object
    30 {
    31   public com.example.springcloud.provider.demo.Demo();
    32     descriptor: ()V
    33     flags: ACC_PUBLIC
    34     Code:
    35       stack=2, locals=1, args_size=1
    36          0: aload_0
    37          1: invokespecial #1                  // Method java/lang/Object."<init>":()V
    38          4: aload_0
    39          5: iconst_1
    40          6: putfield      #2                  // Field isOk:Z
    41          9: return
    42       LineNumberTable:
    43         line 3: 0
    44         line 4: 4
    45       LocalVariableTable:
    46         Start  Length  Slot  Name   Signature
    47             0      10     0  this   Lcom/example/springcloud/provider/demo/Demo;
    48 
    49   public synchronized void test();
    50     descriptor: ()V
    51     flags: ACC_PUBLIC, ACC_SYNCHRONIZED
    52     Code:
    53       stack=2, locals=1, args_size=1
    54          0: aload_0
    55          1: iconst_0
    56          2: putfield      #2                  // Field isOk:Z
    57          5: return
    58       LineNumberTable:
    59         line 7: 0
    60         line 8: 5
    61       LocalVariableTable:
    62         Start  Length  Slot  Name   Signature
    63             0       6     0  this   Lcom/example/springcloud/provider/demo/Demo;
    64 }
    65 SourceFile: "Demo.java"

     改为synchronized代码块:

     1 package com.example.springcloud.provider.demo;
     2 
     3 public class Demo {
     4     private boolean isOk = true;
     5 
     6     public void test() {
     7         synchronized (this) {
     8             isOk = false;
     9         }
    10     }
    11 }

    反编译汇编为:

     1 Classfile /Users/shiwen/IdeaProjects/springcloud/example-springcloud-provider/target/classes/com/example/springcloud/provider/demo/Demo.class
     2   Last modified 2017-10-11; size 536 bytes
     3   MD5 checksum 64305bd51f24f439444d9240efd483fd
     4   Compiled from "Demo.java"
     5 public class com.example.springcloud.provider.demo.Demo
     6   minor version: 0
     7   major version: 52
     8   flags: ACC_PUBLIC, ACC_SUPER
     9 Constant pool:
    10    #1 = Methodref          #4.#21         // java/lang/Object."<init>":()V
    11    #2 = Fieldref           #3.#22         // com/example/springcloud/provider/demo/Demo.isOk:Z
    12    #3 = Class              #23            // com/example/springcloud/provider/demo/Demo
    13    #4 = Class              #24            // java/lang/Object
    14    #5 = Utf8               isOk
    15    #6 = Utf8               Z
    16    #7 = Utf8               <init>
    17    #8 = Utf8               ()V
    18    #9 = Utf8               Code
    19   #10 = Utf8               LineNumberTable
    20   #11 = Utf8               LocalVariableTable
    21   #12 = Utf8               this
    22   #13 = Utf8               Lcom/example/springcloud/provider/demo/Demo;
    23   #14 = Utf8               test
    24   #15 = Utf8               StackMapTable
    25   #16 = Class              #23            // com/example/springcloud/provider/demo/Demo
    26   #17 = Class              #24            // java/lang/Object
    27   #18 = Class              #25            // java/lang/Throwable
    28   #19 = Utf8               SourceFile
    29   #20 = Utf8               Demo.java
    30   #21 = NameAndType        #7:#8          // "<init>":()V
    31   #22 = NameAndType        #5:#6          // isOk:Z
    32   #23 = Utf8               com/example/springcloud/provider/demo/Demo
    33   #24 = Utf8               java/lang/Object
    34   #25 = Utf8               java/lang/Throwable
    35 {
    36   public com.example.springcloud.provider.demo.Demo();
    37     descriptor: ()V
    38     flags: ACC_PUBLIC
    39     Code:
    40       stack=2, locals=1, args_size=1
    41          0: aload_0
    42          1: invokespecial #1                  // Method java/lang/Object."<init>":()V
    43          4: aload_0
    44          5: iconst_1
    45          6: putfield      #2                  // Field isOk:Z
    46          9: return
    47       LineNumberTable:
    48         line 3: 0
    49         line 4: 4
    50       LocalVariableTable:
    51         Start  Length  Slot  Name   Signature
    52             0      10     0  this   Lcom/example/springcloud/provider/demo/Demo;
    53 
    54   public void test();
    55     descriptor: ()V
    56     flags: ACC_PUBLIC
    57     Code:
    58       stack=2, locals=3, args_size=1
    59          0: aload_0
    60          1: dup
    61          2: astore_1
    62          3: monitorenter
    63          4: aload_0
    64          5: iconst_0
    65          6: putfield      #2                  // Field isOk:Z
    66          9: aload_1
    67         10: monitorexit
    68         11: goto          19
    69         14: astore_2
    70         15: aload_1
    71         16: monitorexit
    72         17: aload_2
    73         18: athrow
    74         19: return
    75       Exception table:
    76          from    to  target type
    77              4    11    14   any
    78             14    17    14   any
    79       LineNumberTable:
    80         line 7: 0
    81         line 8: 4
    82         line 9: 9
    83         line 10: 19
    84       LocalVariableTable:
    85         Start  Length  Slot  Name   Signature
    86             0      20     0  this   Lcom/example/springcloud/provider/demo/Demo;
    87       StackMapTable: number_of_entries = 2
    88         frame_type = 255 /* full_frame */
    89           offset_delta = 14
    90           locals = [ class com/example/springcloud/provider/demo/Demo, class java/lang/Object ]
    91           stack = [ class java/lang/Throwable ]
    92         frame_type = 250 /* chop */
    93           offset_delta = 4
    94 }
    95 SourceFile: "Demo.java"

    和synchronized方法对比如下:

     给isOk增加volatile关键字后

     1 Classfile /Users/shiwen/IdeaProjects/springcloud/example-springcloud-provider/target/classes/com/example/springcloud/provider/demo/Demo.class
     2   Last modified 2017-10-11; size 536 bytes
     3   MD5 checksum 8dc910b015c7d5af2feac29d19f519a1
     4   Compiled from "Demo.java"
     5 public class com.example.springcloud.provider.demo.Demo
     6   minor version: 0
     7   major version: 52
     8   flags: ACC_PUBLIC, ACC_SUPER
     9 Constant pool:
    10    #1 = Methodref          #4.#21         // java/lang/Object."<init>":()V
    11    #2 = Fieldref           #3.#22         // com/example/springcloud/provider/demo/Demo.isOk:Z
    12    #3 = Class              #23            // com/example/springcloud/provider/demo/Demo
    13    #4 = Class              #24            // java/lang/Object
    14    #5 = Utf8               isOk
    15    #6 = Utf8               Z
    16    #7 = Utf8               <init>
    17    #8 = Utf8               ()V
    18    #9 = Utf8               Code
    19   #10 = Utf8               LineNumberTable
    20   #11 = Utf8               LocalVariableTable
    21   #12 = Utf8               this
    22   #13 = Utf8               Lcom/example/springcloud/provider/demo/Demo;
    23   #14 = Utf8               test
    24   #15 = Utf8               StackMapTable
    25   #16 = Class              #23            // com/example/springcloud/provider/demo/Demo
    26   #17 = Class              #24            // java/lang/Object
    27   #18 = Class              #25            // java/lang/Throwable
    28   #19 = Utf8               SourceFile
    29   #20 = Utf8               Demo.java
    30   #21 = NameAndType        #7:#8          // "<init>":()V
    31   #22 = NameAndType        #5:#6          // isOk:Z
    32   #23 = Utf8               com/example/springcloud/provider/demo/Demo
    33   #24 = Utf8               java/lang/Object
    34   #25 = Utf8               java/lang/Throwable
    35 {
    36   public volatile boolean isOk;
    37     descriptor: Z
    38     flags: ACC_PUBLIC, ACC_VOLATILE 
    39 
    40   public com.example.springcloud.provider.demo.Demo();
    41     descriptor: ()V
    42     flags: ACC_PUBLIC
    43     Code:
    44       stack=2, locals=1, args_size=1
    45          0: aload_0
    46          1: invokespecial #1                  // Method java/lang/Object."<init>":()V
    47          4: aload_0
    48          5: iconst_1
    49          6: putfield      #2                  // Field isOk:Z
    50          9: return
    51       LineNumberTable:
    52         line 3: 0
    53         line 4: 4
    54       LocalVariableTable:
    55         Start  Length  Slot  Name   Signature
    56             0      10     0  this   Lcom/example/springcloud/provider/demo/Demo;
    57 
    58   public void test();
    59     descriptor: ()V
    60     flags: ACC_PUBLIC
    61     Code:
    62       stack=2, locals=3, args_size=1
    63          0: aload_0
    64          1: dup
    65          2: astore_1
    66          3: monitorenter
    67          4: aload_0
    68          5: iconst_0
    69          6: putfield      #2                  // Field isOk:Z
    70          9: aload_1
    71         10: monitorexit
    72         11: goto          19
    73         14: astore_2
    74         15: aload_1
    75         16: monitorexit
    76         17: aload_2
    77         18: athrow
    78         19: return
    79       Exception table:
    80          from    to  target type
    81              4    11    14   any
    82             14    17    14   any
    83       LineNumberTable:
    84         line 7: 0
    85         line 8: 4
    86         line 9: 9
    87         line 10: 19
    88       LocalVariableTable:
    89         Start  Length  Slot  Name   Signature
    90             0      20     0  this   Lcom/example/springcloud/provider/demo/Demo;
    91       StackMapTable: number_of_entries = 2
    92         frame_type = 255 /* full_frame */
    93           offset_delta = 14
    94           locals = [ class com/example/springcloud/provider/demo/Demo, class java/lang/Object ]
    95           stack = [ class java/lang/Throwable ]
    96         frame_type = 250 /* chop */
    97           offset_delta = 4
    98 }
    99 SourceFile: "Demo.java"
  • 相关阅读:
    网上订餐系统后台代码bug记录与解决
    vector二维数组
    力扣-树-练习题(一)
    优先队列

    并查集
    C++进制转换函数
    平衡二叉树(AVL树)定义与基本操作
    二叉查找树练习题
    树的遍历
  • 原文地址:https://www.cnblogs.com/zhangshiwen/p/7650231.html
Copyright © 2011-2022 走看看