美文网首页
可重入锁机制和源码解析

可重入锁机制和源码解析

作者: superxcp | 来源:发表于2018-12-22 17:22 被阅读0次

一.概述:

锁分为可重入锁和不可重入锁,这两者的区别是什么?
可重入锁就是当一个线程获得了某个对象的实例并进入一个方法A,这个线程在没有释放锁的情况下能否再次进入方法A,就是可重入锁和不可重入锁的区别。

  • 可重入锁:能再次进入方法A,什么情况下需要再次进入方法A,对喽,就是递归调用这个加锁方法执行运算的时候,像synchronized和Reentrantlock都是可重入锁。
  • 不可重入锁:不能再次进入方法A,Mutex(互斥锁)是不可重入锁。

注:在看我这篇文章之前,建议先阅读以下几篇文章,对重入锁有一个大概的了解,顺序也按照我给出的顺序来阅读,我这篇文章只是对可重入锁的源码、CAS、AQS等进行一个总结,对于没有看过AQS或可重入锁的朋友来说不太容易懂。踏下心来看完我推荐的文章,基本对可重入锁(甚至互斥锁及其他锁)有一个比较深入的了解。

1.先学习一下可重入锁的使用方法
https://blog.csdn.net/u012545728/article/details/80843595
https://blog.csdn.net/soonfly/article/details/70918802

2.简单介绍可重入锁的原理,就像作者起的题目一样:轻松学习java可重入锁,这篇文章把可重入锁的机制解释的非常易懂生动。
https://blog.csdn.net/yanyan19880509/article/details/52345422

3.解释完了,直接看源码吧,这篇文章是我看过比较好的一篇介绍可重入锁源码的文章:
https://www.jianshu.com/p/7e1a1903d467

4.看完第三篇,是不是想了解下AQS:强烈推荐下面这篇讲解AQS的文章,妈呀,当我看完这篇文章之后,那叫一个通透,终于知道什么叫大牛,就是不单技术好,博客写的也NB
AQS:https://www.cnblogs.com/waterystone/p/4920797.html

5.读完AQS,是不是也想扫盲下CAS,那来吧:这篇把CAS连带Unsafe类将的比较通俗易懂
CAS:https://blog.csdn.net/mmoren/article/details/79185862

6.最后,记不记得第三篇文章提到了CAS自旋volatile变量,如果还感兴趣的朋友可以参考下这篇文章:
https://blog.csdn.net/holmofy/article/details/73824757

二.可重入锁机制及源码总结:

可重入锁分公平锁和非公平锁:线程老老实实在同步队列排队机制的锁叫公平锁,在之前线程释放锁期间可以加塞的锁叫非公平锁,可重入锁的默认锁是非公平锁。读完上面几篇文章后,可结合我的总结的源码图进行巩固(图片尺寸比较大,下载看更清楚,我传的是高清图),公平锁和非公平锁机制类似,因此这里只拿不公平锁举例。

可重入锁里面有三个内部类,Sync同步类,非公平锁类,公平锁类,其中Sync类给公平锁和非公平锁实现了一些共有方法,比如tryRelease()等方法,也给非公平锁实现了一些特定的比如nonfairTryAcquire()方法(还真是非公平啊...)。

可重入锁最基本最重要的方法就是lock()加锁和unLock()释放锁方法,这里重点介绍这两个方法。

可重入锁源码图.jpg

三.自定义同步器AQS:

谈到并发,不得不谈Reentrantlock,而谈到ReentrantLock,不得不谈AbstractQueuedSynchronizer,就像名字描述的,抽象队列同步器定义了一套多线程访问共享资源的同步器框架,许多类的实现都依赖它,比如
ReentrantLock、Semaphore、CountDownLatch等。

AQS维护了一个volatile state(代表共享资源)和FIFO线程等待队列(多线程竞争资源队列),不同自定义同步器竞争共享资源的方式不同,但自定义同步器在实现时只需实现共享资源state的获取与释放方式即可,至于线程等待队列的维护,AQS已经实现好了,主要有下面几个方法:

  • isHeldExclusively():该线程是否正在独占资源。只有用到condition才需要去实现它。
  • tryAcquire(int):独占方式。尝试获取资源,成功则返回true,失败则返回false。
  • tryRelease(int):独占方式。尝试释放资源,成功则返回true,失败则返回false。
  • tryAcquireShared(int):共享方式。尝试获取资源。负数表示失败;0表示成功,但没有剩余可用资源;正数表示成功,且有剩余资源。
  • tryReleaseShared(int):共享方式。尝试释放资源,如果释放后允许唤醒后续等待结点返回true,否则返回false。

AQS定义两种资源共享方式:独占模式(EXCLUSIVE,只有一个线程能执行,如Reentrantlock)和共享模式(Semaphore、CountDownLatch)。一般来说,自定义同步器要么是独占的,要么是共享的,也可兼有两种模式,比如ReentrantReadWritelock。我们实现某种模式只需要继承AQS,实现tryAcquire和tryRelease方法即可,这也是AQS不是接口而是类的原因,用什么模式只要实现那个模式对应的方法。

四.CAS:

CAS全称CompareAndSwap,核心算法是这样的:

CAS(V,E,N)//V-要更新的变量;E-旧值,或者叫期望值;N-要替换的新值;

在替换为新值之前,比较下变量V是否是当前的期望值,如果相等,替换,不相等,不做动作或重复检测。

锁分为悲观锁和乐观锁,在多线程环境下,

  • 悲观锁:如果在执行动作之前会认为可能发生锁冲突,在执行动作之前加锁的机制为悲观锁,对待操作是一种悲观的态度;
  • 乐观锁:在执行动作之前认为不会发生锁冲突,也不加锁,即无所操作,一旦发生所冲突再去解决冲突的机制为乐观锁,对待操作是一种乐观的态度;

而CAS就是一种乐观锁,他是一种系统级语言,因为系统原语的字节码指令执行时连续的,所以说CAS操作时一条CPU的原子指令操作,不会造成数据不一致的问题。

Unsafe类
我们接着深入一下,CAS在Java的实现环境中必须依赖鲜为人知的Unsafe类,可以理解为CAS操作是Unsafe类的一些方法。Unsafe这个类的方法都是被native()方法修饰的,意思是它的方法可以向操作C指针一样直接操作物理内存,直接调用操作系统底层资源执行相应任务。Unsafe类里CAS的相关操作涉及的方法如下:

//o为指定对象,offset为对象内存的偏移量,偏移量迅速定位字段并设置或获取该字段的值,
expected表示期望值,x表示要设置的值,下面3个方法都通过CAS原子指令执行操作。
public final native boolean compareAndSwapObject(Object o, long offset,Object expected, Object x);
public final native boolean compareAndSwapInt(Object o, long offset,int expected,int x);
public final native boolean compareAndSwapLong(Object o, long offset,long expected,long x);
  • 线程挂起与恢复
    在Java中,线程的挂起与恢复的相关操作被封装在LockSuport类中,但是其底层的还是通过Unsafe类的park()和unPark()方法实现的,
  • CAS使用场景
    从Java1.5开始,提供了java.util.concurrent.atomic包,在该包中有很多基于CAS操作实现的类,比如
AtomicBoolean:原子更新布尔类型
AtomicInteger:原子更新整型
AtomicLong:原子更新长整型

比如AtomicInteger的原子自增方法getAndAddInt()就是实现了CAS操作,从而保证了线程安全,有兴趣的朋友可以去看下源码。

后记:由于能力有限,若有错误或者不当之处,还请大家批评指正,一起学习交流!

相关文章

  • 可重入锁机制和源码解析

    一.概述: 锁分为可重入锁和不可重入锁,这两者的区别是什么?可重入锁就是当一个线程获得了某个对象的实例并进入一个方...

  • Java中的各种锁

    一个线程中的多个流程能不能获取同一把锁:可重入锁和非可重入锁 可重入锁 可重入性:表明了锁的分配机制,是基于线程的...

  • ReentrantLock重入锁和 AQS同步器源码解析

    ReentrantLock重入锁和 AQS同步器源码解析 AQS就是AbstractQueuedSynchroni...

  • Java温故而知新之Lock与Synchronized

    两者比较: 相关概念解析 可重入锁如果锁具备可重入性,则称作为可重入锁。假设方法A需要获取锁,方法B也需要获取锁,...

  • (转)Java中的几种锁机制

    出自:Java中的几种锁机制今天跟着blog整理一下几种锁,比如说 乐观锁和悲观锁,可重入锁和不可重入锁,自旋锁…...

  • 各种锁的概念

    锁的概念 可重入不可重入公平锁非公平锁锁中断通过一个故事理解可重入锁的机制 - 小勇DW3 - 博客园[https...

  • Java 可重入锁 公平锁 读写锁

    1.可重入锁 如果锁具备可重入性,则称作为可重入锁。 像synchronized和ReentrantLock都是可...

  • 可重入锁和非可重入锁

    1 可重入锁 (ReentrantLock和synchronized)可重入锁指的是可重复可递归调用的锁,在外层使...

  • 画分布式锁之"通文馆圣主"Curator的&

    上一篇,我们基于示例和源码去剖析了可重入互斥锁,不可重入互斥锁,信号量锁,参见【画分布式锁之"通文馆圣主"C...

  • J.U.C-AQS-ReentrantLock

    ReentrantLock(可重入锁)和synchronized区别 可重入性 锁的实现(ReentrantLoc...

网友评论

      本文标题:可重入锁机制和源码解析

      本文链接:https://www.haomeiwen.com/subject/vviahqtx.html