Lock -- ReentrantLock 上锁的过程

本文详细解析了AQS(AbstractQueuedSynchronizer)在Java并发中的应用,重点介绍了公平锁和非公平锁的区别,以及ReentrantLock如何利用AQS实现加锁过程。公平锁按线程访问顺序,而非公平锁则是随机竞争。
摘要由CSDN通过智能技术生成

目录

AQS

 公平锁和非公平锁

ReentrantLock定义锁

 加锁过程

AQS

java里大部分的同步锁都是基于AbstractQueuedSynchronizer(简称AQS)实现的,就比如我们经常的遇到的ReentrantLock,ReentrantReadWriteLock,CountDownLatch。

AQS的核心思想就是使用一个队列(FIFO)来保存线程,当某个线程需要上锁的时后,如果锁被占用,就把这个线程加入到队列里,然后把这个线程挂起。当锁被释放的时侯,AQS会从队列里取出一个线程然后唤醒,让线程重新尝试获取锁。

 公平锁和非公平锁

公平锁:每个线程获取锁的顺序都是按照线程访问的先后来决定的,最先获取锁的线程都是最前面的。

非公平锁:每个线程获取锁的顺序都是随机的,不会向公平锁一样遵循“先来后到”,所有线程相互竞争,由cpu决定哪个线程能获取到锁。

ReentrantLock定义锁

ReentrantLock默认是非公平锁,但是我们在创建 ReentrantLock 时,可以手动指定为公平锁。如下源码示例:

入参设置为true, 就可以设定成公平锁

 加锁过程

非公平锁NonfairSyc类(内部类)的tryAcquire(尝试获取锁)方法里,调用了抽象类Sync中的普通方法nonfairTryAcquire,入参是锁状态的更新值,主要逻辑就是获取锁的状态值state,如果是0,就通过CAS机制尝试获取锁,获取成功就上锁成功,如果锁已经被独占,就获取占有锁的线程对象,在原本状态值的基础上增加重入次数,如果小于0,就代表超出锁计数范围,反之,更新state状态值,这个线程仍然持有这个锁。如下源码示例:

公平锁:在内部类FairSync中,尝试获取公平锁的逻辑是,先判断状态是不是0,是0就表示没有线程占用锁,不是就表示锁已经被占用,没有占用当前线程就尝试占用锁,先判断sync队列(AbstractQueuedSynchronizer中的数据结构)里有没有等待时间更长的线程以及期望值和更新值是否一致。满足条件,就修改参数,也就是获取锁,不满足,则获取锁失败。如果锁被占用,具体逻辑和非公平锁的流程一样。如下源码示例:

  • 15
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值