通过抢厕所理解Java中的信号量Semaphore

信号量是一个并发工具类,(重复)是一个工具类,控制并发线程数,内部保存有虚拟的许可数量,线程执行操作时候要先获得许可,执行完毕释放许可,如果没有可用许可,则阻塞直到其它线程释放。

init(也就是new Semaphore)方法进行许可数的初始化
release方法释放许可
Acquire方法申请许可,元子操作

假设有个临界资源A
每次只允许一个线程访问,所以许可初始化为1,利用信号量就可以做隔离
线程t1和t2都要访问临界资源A
t1,t2都进行acquire,元子操作许可-1,t1获得许可,t2阻塞
t1执行完了,释放许可,唤醒t2进行操作

信号量还允许指定数量的多个线程进行访问一个临界区,这一点就是类似于限流器,注意在许可数量为0时,信号量是每释放一个许可就唤醒一条线程,线程被唤醒后直接执行任务,不会再判断许可(默认有一个许可释放),这样的好处是节约了唤醒多个线程又进行一轮许可争抢和判断的开销

这里用个抢厕所坑位的例子,十个人,三个厕所坑位,只能一个拉完下一个才能过来拉
public static void main(String[] args) throws Exception {
    // 抢厕所 (许可数量,是否公平获取,公平则顺序唤醒,非公平随机唤醒)
    Semaphore semaphore = new Semaphore(3, true);
    ExecutorService executor = Executors.newCachedThreadPool();
    for (int i = 0; i < 10; i++) {
        final int customer = i;
        Runnable run = () -> {
            try {
                // 获取许可(抢到厕所)
                semaphore.acquire();
                System.out.println("客人"+customer+"抢到厕所");
                // 正在如厕(时间不定)
                Thread.sleep((long) (Math.random() * 10000));
                // 拉完释放
                semaphore.release();
                System.out.println("客人"+customer+"拉完了");
            } catch (Exception e){}
        };
        executor.execute(run);
    }
    try {
        Thread.sleep(10);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    // 退出线程池
    executor.shutdown();
}

在这里插入图片描述

通过以上例子,我们可以把厕所想象成一些资源,例如临界资源,一些共享区,为了保证资源的安全和可用,就要加以限制,这个时候就可以使用信号量
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值