zoukankan      html  css  js  c++  java
  • volatile关键字和synchronized关键字

    volatile关键字:

    可以用来修饰字段(成员变量),就是告知程序任何对该变量的访问均需要从共享内存中获取,而对它的改变必须同步刷新回共享内存,它能保证所有线程对变量访问的可见性。

    synchronized关键字:

    可以修饰方法或以同步块的形式来进行使用,它主要确保多个线程在同一时刻,只能有一个线程处于方法或者同步块中,它保证了对变量访问的可见性和排他性。

    package com.baidu.nuomi.concurrent;
    
    /**
     * Created by sonofelice on 16/6/18.
     */
    public class Synchronized {
        public static void main(String[] args) {
            synchronized (Synchronized.class){
    
            }
        }
        public static synchronized void m(){}
    }

    使用javap查看生成的class文件:

    在该类的同级目录下执行javap -v Synchronized.class

    得到下面的结果:

    Classfile /Users/sonofelice/Downloads/zhmmself/target/classes/com/baidu/nuomi/concurrent/Synchronized.class
      Last modified 2016-6-18; size 590 bytes
      MD5 checksum 64550d9817510bcc5d531e20e814b122
      Compiled from "Synchronized.java"
    public class com.baidu.nuomi.concurrent.Synchronized
      SourceFile: "Synchronized.java"
      minor version: 0
      major version: 50
      flags: ACC_PUBLIC, ACC_SUPER
    Constant pool:
       #1 = Methodref          #3.#22         //  java/lang/Object."<init>":()V
       #2 = Class              #23            //  com/baidu/nuomi/concurrent/Synchronized
       #3 = Class              #24            //  java/lang/Object
       #4 = Utf8               <init>
       #5 = Utf8               ()V
       #6 = Utf8               Code
       #7 = Utf8               LineNumberTable
       #8 = Utf8               LocalVariableTable
       #9 = Utf8               this
      #10 = Utf8               Lcom/baidu/nuomi/concurrent/Synchronized;
      #11 = Utf8               main
      #12 = Utf8               ([Ljava/lang/String;)V
      #13 = Utf8               args
      #14 = Utf8               [Ljava/lang/String;
      #15 = Utf8               StackMapTable
      #16 = Class              #14            //  "[Ljava/lang/String;"
      #17 = Class              #24            //  java/lang/Object
      #18 = Class              #25            //  java/lang/Throwable
      #19 = Utf8               m
      #20 = Utf8               SourceFile
      #21 = Utf8               Synchronized.java
      #22 = NameAndType        #4:#5          //  "<init>":()V
      #23 = Utf8               com/baidu/nuomi/concurrent/Synchronized
      #24 = Utf8               java/lang/Object
      #25 = Utf8               java/lang/Throwable
    {
      public com.baidu.nuomi.concurrent.Synchronized();
        flags: ACC_PUBLIC
        Code:
          stack=1, locals=1, args_size=1
             0: aload_0       
             1: invokespecial #1                  // Method java/lang/Object."<init>":()V
             4: return        
          LineNumberTable:
            line 6: 0
          LocalVariableTable:
            Start  Length  Slot  Name   Signature
                   0       5     0  this   Lcom/baidu/nuomi/concurrent/Synchronized;
    
      public static void main(java.lang.String[]);
        flags: ACC_PUBLIC, ACC_STATIC
        Code:
          stack=2, locals=3, args_size=1
             0: ldc_w         #2                  // class com/baidu/nuomi/concurrent/Synchronized
             3: dup           
             4: astore_1      
             5: monitorenter  
             6: aload_1       
             7: monitorexit   
             8: goto          16
            11: astore_2      
            12: aload_1       
            13: monitorexit   
            14: aload_2       
            15: athrow        
            16: return        
          Exception table:
             from    to  target type
                 6     8    11   any
                11    14    11   any
          LineNumberTable:
            line 8: 0
            line 10: 6
            line 11: 16
          LocalVariableTable:
            Start  Length  Slot  Name   Signature
                   0      17     0  args   [Ljava/lang/String;
          StackMapTable: number_of_entries = 2
               frame_type = 255 /* full_frame */
              offset_delta = 11
              locals = [ class "[Ljava/lang/String;", class java/lang/Object ]
              stack = [ class java/lang/Throwable ]
               frame_type = 250 /* chop */
              offset_delta = 4
    
    
      public static synchronized void m();
        flags: ACC_PUBLIC, ACC_STATIC, ACC_SYNCHRONIZED
        Code:
          stack=0, locals=0, args_size=0
             0: return        
          LineNumberTable:
            line 12: 0
    }

    分析一下synchronized关键字的实现细节。

    上面class信息中,对于同步块的实现使用了

    monitorenter  和   monitorexit

    指令。而同步方法则是依靠方法修饰符上的

    ACC_SYNCHRONIZED

    来完成的。

    无论哪种方式,其本质是对一个对象的监视器进行获取,而这个获取的过程是排他的,也就是同一时刻只能有一个线程获取到由synchronized所保护对象的监视器。

    任意一个对象都拥有自己的监视器,当这个对象由同步块或者这个对象的同步方法调用时,执行方法的线程必须先获取到该对象的监视器才能进入同步块或者同步方法,而没有获取到监视器(执行该方法)的线程将会被阻塞在同步块和同步方法的入口处,进入BLOCKED状态。

  • 相关阅读:
    【习题 3-12 UVA
    【习题 3-9 UVA
    【Codeforces Round #299 (Div. 2) E】Tavas and Pashmaks
    分布式ID生成器的解决方案总结
    Spring MVC表单防重复提交
    Spring import配置文件使用占位符
    什么是灰度发布,灰度测试。
    浅析负载均衡的6种算法,Ngnix的5种算法。
    神器,阿里巴巴Java代码检查插件
    去BAT面试完的Mysql面试题总结(55道,带完整答案)
  • 原文地址:https://www.cnblogs.com/sonofelice/p/5595827.html
Copyright © 2011-2022 走看看