前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java并发——通过ReentrantLock和Semaphore揭秘AQS独占模式与共享模式

Java并发——通过ReentrantLock和Semaphore揭秘AQS独占模式与共享模式

原创
作者头像
淇妙小屋
发布2022-04-01 09:11:23
4420
发布2022-04-01 09:11:23
举报
文章被收录于专栏:面试题详解面试题详解

大家好,这里是淇妙小屋,一个分享技术,分享生活的博主

以下是我的主页,各个主页同步更新优质博客,创作不易,还请大家点波关注

掘金主页

后续会发布更多MySQL,Redis,并发,JVM,分布式等面试热点知识,以及Java学习路线,面试重点,职业规划,面经等相关博客

转载请标明出处!

本文将通过ReentrantLock和Semaphore带你看看AQS的独占模式和共享模式是怎么实现的

  • ReentrantLock实现了AQS的独占模式
  • Semaphore实现了AQS的共享模式

1. ReentrantLock介绍

可重入:任意线程获得锁后能够再次获取该锁而不会被锁阻塞

ReentrantLock实现了AQS的独占模式,是一个可重入锁,还分为 公平锁非公平锁

  • 公平锁:先对锁进行获取请求的线程一定先获得锁
  • 非公平锁

非公平锁的效率高于公平锁

非公平锁可能出现 线程饥饿问题——部分线程迟迟无法获得资源

ReentrantLock.png
ReentrantLock.png

ReentrantLock大多数方法的实现都是Sync及其子类来完成,ReentrantLock只是对外暴露了接口

2. ReentrantLock获得锁

2.1 非公平锁
ReentrantLock非公平锁获得锁.png
ReentrantLock非公平锁获得锁.png
2.2 公平锁
ReentrantLock公平锁获得锁.png
ReentrantLock公平锁获得锁.png
2.3 公平锁与非公平锁的不同

FairSync和NonfairSync的 lock() 和 tryAcquire() 逻辑不同

  1. 非公平锁在lock()方法的开始就会尝试去通过CAS修改同步状态以获得锁,公平锁不会
  2. 在自旋时,非公平锁和公平锁都会在前继节点为同步队列首节点时调用tryAcquire()尝试获取锁

tryAcquire()中,如果state为0,那么非公平锁不会关心节点在同步队列中的位置,直接尝试CAS修改state获得锁;但是非公平锁关心节点的位置,会检查是否有前继节点,如果有,就会放弃

上述2点保证了公平锁一定是——先对锁进行获取请求的线程一定先获得锁,而非公平锁不一定

3. ReentrantLock释放锁

公平锁释放锁与非公平锁释放锁采用同一个逻辑

ReentrantLock非公平锁释放锁.png
ReentrantLock非公平锁释放锁.png

4. Semaphore介绍

Semaphore实现了AQS的共享模式

信号量,用来控制同时访问特定资源的线程数目

初始化时指定信号量(permits)的数目(本质还是AQS的state)

如果线程想要访问一个资源,必须先获得信号量减少,信号量为0时,线程无法访问资源,只能WATING等待信号量>0,

如果使用完资源,释放后,会补充信号量

(之前的ReentrantLock中state=0表示锁可用,state不为0表示锁不可用,Semaphore这里state不为0表示锁可用,state为0表示锁不可用)

Semaphore..png
Semaphore..png

5. Semaphore方法介绍

代码语言:java
复制
//尝试获取一个信号量,如果信号量不为0,那么将信号量-1,返回
//如果信号量为0,WAITING直到信号量不为0
//可中断
public void acquire() throws InterruptedException

//尝试获取多个信号量,如果信号量足够,那么将信号量-permits,返回
//如果信号量不够,WAITING直到信号量不为0
//可中断 
public void acquire(int permits) throws InterruptedException
    
//同acquire(),但不可中断
public void acquireUninterruptibly()
    
//同acquire(int permits),但不可中断
public void acquireUninterruptibly(int permits)

//释放一个信号量
public void release()
    
//释放permits个信号量
public void release(int permits)

6. 方法详解

6.1 void acquire(int permits)

底层调用的还是AQS共享模式获取锁的那一套

AQS共享模式获得锁.png
AQS共享模式获得锁.png

公平模式——FariSync中的 tryAcquireShared(int acquires)

Semaphore的acquire().png
Semaphore的acquire().png

非公平模式——NonfairSync中的 tryAcquireShared(int acquires)调用Sync中的 nonfairTryAcquireShared(int acquires)

23.png
23.png
6.2 void release(int requires)

底层调用的还是AQS共享模式释放锁的那一套

AQS共享模式释放锁.png
AQS共享模式释放锁.png

Sync实现了 tryReleaseShared(int releases)

Semaphore的tryReleaseShared.png
Semaphore的tryReleaseShared.png

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. ReentrantLock介绍
  • 2. ReentrantLock获得锁
    • 2.1 非公平锁
      • 2.2 公平锁
        • 2.3 公平锁与非公平锁的不同
        • 3. ReentrantLock释放锁
        • 4. Semaphore介绍
        • 5. Semaphore方法介绍
        • 6. 方法详解
          • 6.1 void acquire(int permits)
            • 6.2 void release(int requires)
            相关产品与服务
            云数据库 MySQL
            腾讯云数据库 MySQL(TencentDB for MySQL)为用户提供安全可靠,性能卓越、易于维护的企业级云数据库服务。其具备6大企业级特性,包括企业级定制内核、企业级高可用、企业级高可靠、企业级安全、企业级扩展以及企业级智能运维。通过使用腾讯云数据库 MySQL,可实现分钟级别的数据库部署、弹性扩展以及全自动化的运维管理,不仅经济实惠,而且稳定可靠,易于运维。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档