Java 之 Semaphore 原理篇

6 篇文章 0 订阅
3 篇文章 0 订阅

引言

Semaphore 就像是饭堂,饭堂有固定的桌位,在吃饭高峰期时就要来早点抢位,不然桌位坐满了就得等别人吃完才有桌位吃饭;

测试示例

import java.util.Random;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

public class SemaphoreTest {

    public static void main(String[] args) {
        Semaphore semaphore = new Semaphore(3); // 设置可用资源数 3
        for (int i = 0; i < 5; i++) {
            new Thread(() -> {
                try {
                    semaphore.acquire(); // 抢占资源
                    System.out.println(Thread.currentThread().getName() + " 抢到桌位,开始吃饭");
                    TimeUnit.SECONDS.sleep(new Random().nextInt(5));
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    System.out.println(Thread.currentThread().getName() + " 吃完饭,离开桌位");
                    semaphore.release(); // 释放
                }
            }, "t" + i).start();
        }
    }
}

输出结果:
在这里插入图片描述
以上示例为总3张桌位,5批人来吃饭,0、1、4先抢到桌位入座,2、3等别人离开后入座

Semaphore 源码

public class Semaphore implements java.io.Serializable {
	private final Sync sync;
	abstract static class Sync extends AbstractQueuedSynchronizer {}
	// 不公平版本 (默认)
	static final class NonfairSync extends Sync {}
	// 公平版本
	static final class FairSync extends Sync {}
}

Semaphore 内部定义了一个 Sync 内部类实现了 AbstractQueuedSynchronizer 同步器;
派生出 NonfairSync 和 FairSync两个版本的实现

acquire 抢占资源

semaphore.acquire() 方法用于抢占资源
在这里插入图片描述
跟踪源码 acquire() 调用最终会进入Sync.nonfairTryAcquireShared(),并且对state的值原子性减1,state是 AbstractQueuedSynchronizer 维护的一个状态值,也可以说是计数器,可以说AbstractQueuedSynchronizer同步器的实现很大程度都依靠 state 来实现;前3个抢占到资源的线程每个都对 state 的值减1;
在这里插入图片描述
![在这里插入图片描述](https://img-blog.csdnimg.cn/41f14459088b417c85c6da7b8775bb7d.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5YC-5bC95YWo5Yqb57uI5peg5oKU,size_20,color_FFFFFF,t_70,g_se,x_16
在这里插入图片描述
当第4个线程进来时,并没有可用的资源使用,此时 state 的值为0,进入doAcquireSharedInterruptibly() 方法,对于没有抢占到资源的线程会维护成一个链表的形式,最后调用 LockSupport.park(this) 挂起该线程;

release 释放资源

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
释放资源就是对 state 的值加 1;并且调用 LockSupport.unpark() 唤醒链表中的其他线程

总结

Semaphore 内部维护了一个Sync 实现 AbstractQueuedSynchronizer 同步器来实现的功能,AbstractQueuedSynchronizer 还真是一个好东西;

Semaphore → AbstractQueuedSynchronizer → (state、链表、LockSupport)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值