Java并发-synchronizd锁原理

原创 2018年04月14日 22:04:27

synchronized在印象中是一个解决线程安全问题对神器,但它的效率却不怎么高。在jdk1.6以后,synchronized已经不再是一个简单粗暴的线程锁了,通过引入偏向锁/轻量级锁等机制对其进行了一系列优化。

synchronized的用法

synchronized的用法主要有三种

  1. 静态同步方法
  2. 普通同步方法
  3. 同步代码块

这三种应用形式的区别在于

  • 静态同步方法用的锁对象是当前类的class对象
  • 普通同步方法用的锁对象是当前对象
  • 同步代码块用的锁对象是指定的一个已存在的对象

代码实例如下:

public static synchronized void method1(){
    ....
}

public synchronized void method2() {
    ...
}

private Object lockObj = new Object();
public void method3(){
    synchronized(lockObj) {
        ...
    }
}

synchronized锁原理

��️上面可知,synchronized的使用主要分两种,一种是方法级别的,一种是同步代码块,对于这两种方式,底层的实现原理有所不同。

synchronized同步代码块

同步代码块是通过java编译器在临界区的开始和结束位置插入monitorentermonitorexit指令来实现同步的。每个monitorenter都必须对应一个monitorexit,又一个每个java对象都有一个monitor与之关联,当执行monitorenter时,当前线程会尝试持有锁对应对应当monitor,当执行monitorexit时,会释放已经获取当monitor

synchronized同步方法

同步方法并没有在指令层面假如任何的同步指令,而是在Class文件的方法表中将该方法的access_flags字段中的synchronized标志位置1,表示该方法是同步方法并使用调用该方法的对象或该方法所属的Class在JVM的内部对象表示Klass做为锁对象。

对象头

synchronized用的锁是存储在Java对象头里面的,Hotspot虚拟机的对象头主要包括两部分数据:Mark Word(标记字段)、Klass Pointer(类型指针)。其中Klass Point是是对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例,Mark Word用于存储对象自身的运行时数据,它是实现轻量级锁和偏向锁的关键。

对象头信息是与对象自身定义的数据无关的额外存储成本,但是考虑到虚拟机的空间效率,Mark Word被设计成一个非固定的数据结构以便在极小的空间内存存储尽量多的数据,它会根据对象的状态复用自己的存储空间,也就是说,Mark Word会随着程序的运行发生变化,变化状态如下(32位虚拟机):
这里写图片描述
参考:ImportNew

synchronized锁的种类

在jdk1.6中引入了偏向锁/轻量级锁来优化synchronized原有的单一重量级锁,这几种锁的级别从底到高分别为 偏向锁->轻量级锁->重量级锁,随着对共享资源竞争激烈程度的怎加锁的级别逐渐增加,直到重量级锁。

锁可以升级,但不能降级,也就是不能从重量级锁降级为偏向锁。

偏向锁

引入偏向锁的目的是减少在无竞争状态下获取锁和释放锁的开销。

获取偏向锁的流程:

  1. 检查锁对象的MarkWorld是否为偏向锁
  2. 如果是偏向锁,则检查偏向的线程id是否为当前线程id
  3. 如果偏向锁指向当前线程,则直接进入临界区
  4. 如果偏向锁指向其他线程,则当前线程通过cas竞争偏向锁,也就是将锁偏向的线程id指向当前线程id
  5. 如果设置成功,则竞争锁成功,进入临界区
  6. 如果设置失败,则说明共享资源出现竞态,将锁升级为轻量级锁

偏向锁的获取流程:
偏向锁的释放采用来一种只有出现竞争才释放锁的策略,偏向锁不会被主动释放,偏向锁的释放需要等待一个全局安全点,也就是一个稳定的状态

  1. 挂起持有偏向锁的线程,判断锁对象释放处于锁定状态
  2. 撤销偏向锁,恢复到无锁状态或升级为轻量级锁

轻量级锁

轻量级锁也是为了解决重量级锁的性能问题, 针对共享资源的竞争但线程的任务很轻,很快就会执行完情况。

轻量级锁的获取流程:

  1. 判断当前锁是否处于锁定状态,如果是,则在当前线程的栈桢上创建一个名为锁记录的空间,用来存储锁对象的mark word的拷贝
  2. 利用cas将锁对象中的mark workd指向当前线程的锁记录(mark word的拷贝),如果设置整个则获取锁成功
  3. 如果设置失败,则判断当前锁对象的mark word是否指向当前线程的锁记录,如果是,则说明当前线程之前已经获取过锁,直接进入临界区,如果不是,则说明存在竞争条件,将锁升级为重量级锁

轻量级锁的是否过程

  1. 取出在获取轻量级锁保存在Displaced Mark Word中的数据;
  2. 用CAS操作将取出的数据替换当前对象的Mark Word中,如果成功,则说明释放锁成功,
  3. 如果CAS操作替换失败,说明有其他线程尝试获取该锁,则需要在释放锁的同时需要唤醒被挂起的线程

锁总结

  • 偏向锁适用于单线程访问临界区情况
  • 轻量级锁适用于存在并发,但由于临界区执行速度很快不会出现竞争但情况
  • 重量级锁就是传统的锁,适用于任何场景,只是由于线程会被挂起,带来额外的开销以及影响系统的吞吐率
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zhangdong2012/article/details/79944851

Java并发机制及锁的实现原理

Java并发机制及锁实现原理
  • sunxianghuang
  • sunxianghuang
  • 2016-07-18 20:04:21
  • 13295

JAVA并发机制的底层实现原理

JAVA代码在编译后会变成字节码,字节码被类加载器加载到JVM中,JVM执行字节码,最终需要转化为汇编指令在CPU上执行,JAVA中所使用的并发机制依赖于JVM的实现和CPU的指令。 1.volati...
  • qq_16811963
  • qq_16811963
  • 2016-08-10 16:17:09
  • 3565

JAVA并发原理(下)

VolatileVolatile关键字用于确保共享数据的可见性与有序性,但是并不能保证方法的原子性,在程序中对Volatile关键字使用得当的话,它比synchronized的使用和执行成本会更低,因...
  • witness_mei
  • witness_mei
  • 2016-03-02 23:09:38
  • 345

java并发编程——四(synchronized\Lock\volatile) 锁机制原理及关联

前言 其实标题使用互斥机制更合适,并发中主要两个问题是:线程如何同步以及线程如何通信。 同步主要是通过互斥机制保证的,而互斥机制我们最熟悉的就是锁,当然也有无锁的CAS实现。 多线程共享资源,比...
  • lemon89
  • lemon89
  • 2016-02-25 23:10:28
  • 1562

java高并发锁的3种实现

提到锁,大家可能都会想到synchronized关键字,使用它的确可以解决一切并发问题,但是对于系统吞吐要求更高的,在这里提供了几个小技巧,帮助大家减小锁粒度,提高系统并发能力。 ...
  • hl_java
  • hl_java
  • 2017-04-12 22:36:01
  • 9723

集群环境下防止并发的一种实现( Spring Quartz 集群思路)

转自:http://bbs.chinaunix.net/thread-3685716-1-1.html  近来研究定时器Quartz集群的实现原理时,发现了一种利用数据库锁的方式来实现集群环...
  • liuyuhua0066
  • liuyuhua0066
  • 2014-08-29 10:57:21
  • 4660

JDK1.8版本,java并发框架支持锁包括

1、自旋锁,自旋,jvm默认是10次,由jvm自己控制,for去争取锁 2、阻塞锁 被阻塞的线程,不会争夺锁 3、可重入锁,多次进入改锁的域 4、读写锁 5、互斥锁,锁本身就是互斥的 6、悲观锁,不相...
  • wenwen360360
  • wenwen360360
  • 2017-03-15 21:58:13
  • 1919

深入理解Java并发之synchronized实现原理

【版权申明】未经博主同意,谢绝转载!(请尊重原创,博主保留追究权) http://blog.csdn.net/javazejian/article/details/72828483 ...
  • javazejian
  • javazejian
  • 2017-06-04 17:44:44
  • 51530

java高并发:CAS无锁原理及广泛应用

前言在现在的互联网技术领域,用户流量越来越大,系统中并发量越来越大,大公司的日活动辄成百上千万。如何面对如此高的并发是当今互联网技术圈一直在努力的事情。 应对高并发需要在各个技术层面进行合理的设计和...
  • fgyibupi
  • fgyibupi
  • 2016-12-20 12:53:39
  • 7459

Java轻量级锁(自旋锁)和偏向锁原理

  • 2013年10月13日 10:10
  • 695KB
  • 下载
收藏助手
不良信息举报
您举报文章:Java并发-synchronizd锁原理
举报原因:
原因补充:

(最多只允许输入30个字)