ReentrantLock
IT面试
602 ·
0 ·
2023-02-08 16:46:52
最新编辑原因:

enter image description here

ReentrantLock原理(CAS+AQS)

CAS+AQS队列来实现:

  • 先通过CAS尝试获取锁, 如果此时已经有线程占据了锁,那就加入AQS队列并且被挂起

  • 当锁被释放之后, 排在队首的线程会被唤醒CAS再次尝试获取锁

  • 如果是非公平锁, 同时还有另一个线程进来尝试获取可能会让这个线程抢到锁;

  • 如果是公平锁, 会排到队尾,由队首的线程获取到锁。

1. CAS

  1. 原理
    内存值V,旧的预期值A,要修改的新值B,当A=V时,将内存值修改为B,否则什么都不做;

  2. 缺点

    1. ABA问题

    2. 如果CAS失败,自旋会给CPU带来压力

    3. 只能保证对一个变量的原子性操作,i++这种是不能保证的

  3. CAS在java中的应用
    Atomic系列

2. AQS (AbstractQueuedSynchronizer)
队列同步器,这是实现 ReentrantLock 的基础

原理
enter image description here

AQS 有一个 state 标记位,值为1 时表示有线程占用,其他线程需要进入到同步队列等待,同步队列是一个双向链表。

Node内部类构成的一个双向链表结构的同步队列,通过控制(volatile的int类型)state状态来判断锁的状态,对于非可重入锁状态不是0则去阻塞;
对于可重入锁如果是0则执行,非0则判断当前线程是否是获取到这个锁的线程,是的话把state状态+1,比如重入5次,那么state=5。 而在释放锁的时候,同样需要释放5次直到state=0其他线程才有资格获得锁

AQS两种资源共享方式

  1. Exclusive:独占,只有一个线程能执行,如ReentrantLock

  2. Share:共享,多个线程可以同时执行,如Semaphore、CountDownLatch、ReadWriteLock,CyclicBarrier

synchronized与ReentrantLock区别

  1. 都是可重入锁; ReentrantLock是显示获取和释放锁,synchronized是隐式;

  2. ReentrantLock更灵活可以知道有没有成功获取锁,可以定义读写锁,是api级别,synchronized是JVM级别;

  3. ReentrantLock可以定义公平锁;Lock是接口,synchronized是java中的关键字

ReentrantLock 是如何实现可重入性的?

内部自定义了同步器 Sync,加锁的时候通过CAS 算法 ,将线程对象放到一个双向链表中,每次获取锁的时候 ,看下当前维护的那个线程ID和当前请求的线程ID是否一样,一样就可重入了;

ReentrantLock如何避免死锁?

  • 响应中断lockInterruptibly()

  • 可轮询锁tryLock()

  • 定时锁tryLock(long time)


本作品系原创,采用《署名-非商业性使用-禁止演绎4.0 国际》许可协议.转载请说明出处
本文链接:https://www.upupor.com/u/Xxbl86L 复制

无内容

推荐阅读