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状态。

最新文章

  1. Myeclipse不显示js文件错误的方法
  2. Torch7 Tensor切片总结
  3. bzoj2683
  4. file_put_contents保存数据,
  5. Less入门到上手——前端开发利器&lt;一&gt;
  6. centos7开启3306端口,liunx查看防火墙是否开启
  7. LeetCode-Group Shifted Strings
  8. iOS - UIGestureRecognizer
  9. PureMVC(JS版)源码解析(三):Observer类
  10. Java利用httpasyncclient进行异步HTTP请求
  11. [Android开发常见问题-11] Unable to execute dex: Multiple dex files define 解决方法
  12. linux系统和Windows系统共存
  13. 如何构建Android MVVM 应用框架
  14. ps切图技巧
  15. P1216 数字三角形
  16. includes() 方法
  17. mysql的高级特性-存储过程
  18. Android Launcher分析和修改8——AllAPP界面拖拽元素(PagedViewWithDraggableItems)
  19. ashx和aspx的区别
  20. 作业:WordCount--实现字符数,单词数,行数的统计

热门文章

  1. Nagios 系统监控基本安装配置过程详解
  2. CodeForces758D
  3. KB奇遇记(3):IT现状
  4. A tutorial on Principal Components Analysis | 主成分分析(PCA)教程
  5. esri-leaflet入门教程(1)-leaflet介绍
  6. Terminating app due to uncaught exception &#39;NSInvalidArgumentException&#39;, reason: &#39;-[NSInvocation setArgument:atIndex:]: index (3) out of bounds [-1, 2]&#39;
  7. Java语言跨平台原理
  8. 根据dba_hist_osstat统计CPU占用情况
  9. int装箱比较
  10. [Kafka] - Kafka 安装介绍