【死磕Java并发】-----J

public Semaphore(int permits) {

sync = new NonfairSync(permits);

}

public Semaphore(int permits, boolean fair) {

sync = fair ? new FairSync(permits) : new NonfairSync(permits);

}

复制代码

Semaphore默认选择非公平锁。

当信号量Semaphore = 1 时,它可以当作互斥锁使用。其中0、1就相当于它的状态,当=1时表示其他线程可以获取,当=0时,排他,即其他线程必须要等待。

信号量获取

Semaphore提供了acquire()方法来获取一个许可。

public void acquire() throws InterruptedException {

sync.acquireSharedInterruptibly(1);

}

复制代码

内部调用AQS的acquireSharedInterruptibly(int arg),该方法以共享模式获取同步状态:

public final void acquireSharedInterruptibly(int arg)

throws InterruptedException {

if (Thread.interrupted())

throw new InterruptedException();

if (tryAcquireShared(arg) < 0)

doAcquireSharedInterruptibly(arg);

}

复制代码

在acquireSharedInterruptibly(int arg)中,tryAcquireShared(int arg)由子类来实现,对于Semaphore而言,如果我们选择非公平模式,则调用NonfairSync的tryAcquireShared(int arg)方法,否则调用FairSync的tryAcquireShared(int arg)方法。

公平

protected int tryAcquireShared(int acquires) {

for (;😉 {

//判断该线程是否位于CLH队列的列头

if (hasQueuedPredecessors())

return -1;

//获取当前的信号量许可

int available = getState();

//设置“获得acquires个信号量许可之后,剩余的信号量许可数”

int remaining = available - acquires;

//CAS设置信号量

if (remaining < 0 ||

compareAndSetState(available, remaining))

return remaining;

}

}

复制代码

非公平

对于非公平而言,因为它不需要判断当前线程是否位于CLH同步队列列头,所以相对而言会简单些。

protected int tryAcquireShared(int acquires) {

return nonfairTryAcquireShared(acquires);

}

l int nonfairTryAcquireShared(int acquires) {

for (;😉 {

int available = getState();

int remaining = available - acquires;

if (remaining < 0 ||

compareAndSetState(available, remaining))

return remaining;

}

}

复制代码

信号量释放

获取了许可,当用完之后就需要释放,Semaphore提供release()来释放许可。

public void release() {

sync.releaseShared(1);

}

复制代码

内部调用AQS的releaseShared(int arg):

public final boolean releaseShared(int arg) {

if (tryReleaseShared(arg)) {

doReleaseShared();

return true;

}

return false;

}

复制代码

releaseShared(int arg)调用Semaphore内部类Sync的tryReleaseShared(int arg):

protected final boolean tryReleaseShared(int releases) {

for (;😉 {

int current = getState();

//信号量的许可数 = 当前信号许可数 + 待释放的信号许可数

int next = current + releases;

if (next < current) // overflow

throw new Error(“Maximum permit count exceeded”);

//设置可获取的信号许可数为next

if (compareAndSetState(current, next))

return true;

}

}

复制代码

对于信号量的获取释放详细过程,请参考如下博客:

  1. 【死磕Java并发】-----J.U.C之AQS:CLH同步队列

  2. 【死磕Java并发】-----J.U.C之AQS:同步状态的获取与释放

  3. 【死磕Java并发】-----J.U.C之AQS:阻塞和唤醒线程

  4. 【死磕Java并发】-----J.U.C之重入锁:ReentrantLock

应用示例


我们已停车为示例:

public class SemaphoreTest {

static class Parking{

//信号量

private Semaphore semaphore;

Parking(int count){

semaphore = new Semaphore(count);

}

public void park(){

try {

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

总结

其他的内容都可以按照路线图里面整理出来的知识点逐一去熟悉,学习,消化,不建议你去看书学习,最好是多看一些视频,把不懂地方反复看,学习了一节视频内容第二天一定要去复习,并总结成思维导图,形成树状知识网络结构,方便日后复习。

这里还有一份很不错的《Java基础核心总结笔记》,特意跟大家分享出来

目录:

部分内容截图:


《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
思维导图,形成树状知识网络结构,方便日后复习。

这里还有一份很不错的《Java基础核心总结笔记》,特意跟大家分享出来

目录:

[外链图片转存中…(img-79zcRCn0-1713550466439)]

部分内容截图:

[外链图片转存中…(img-a3ifXsEK-1713550466439)]

[外链图片转存中…(img-TnkjqtWZ-1713550466440)]
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

  • 28
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值