Java并发编程(9)——信号量

本文介绍了Semaphore的基本概念及其简单实现,并探讨了如何通过限制信号数量来作为锁使用的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

Semaphore是一个线程同步结构,用于在线程之间传递信号以免出现信号丢失,或者像锁一样保护一个关键区域。Java5之后, java.util.concurrent中提供了Semaphore的实现,我们不再自行实现,而是了解其原理。

1. 简单的Semaphore实现

public class Semaphore{
    private boolean signal=false;

    public synchronized take(){
        this.signal=true;
        this.notify();
    }

    public synchronized release() throws InterruptedException{
        while(!this.signal)
            wait();
        this.signal=false;
    }
}

take()方法发出了一个存放在Semaphore内部的信号,而release()方法则等待一个信号,当收到信号后,signal被置为false,方法结束。
使用该Semaphore可以避免错失某些信号,如果某个线程在调用release()等待之前调用take(),那么调用release()方法的线程依然知道take()已经被某个线程调用过了,因为Semaphore内部保存了take方法发出的信号。方法名takerelease来源于将Semaphore当做锁来使用的场景。

2. 限制Semaphore的计数上限

public class BoundedSemaphore{
    private int signals=0;
    private int bound=0;

    public BoundedSemaphore(int upperBound){
        this.bound=upperBound;
    }

    public synchronized take() throws InterruptedException{
        while(this.signals==bound)
            wait();
        this.signals++;
        this.notify();
    }

    public sychronized release() throws InterruptedException{
        while(this.signal==0)
            wait();
        this.signal--;
        this.notify();
    }
}

在这里,当信号数达到上限时,take()方法将阻塞新的信号产生请求,直到某个请求调用release()方法后,被阻塞于take方法的线程才能传递自己的信号。
这里对信号数的上限做限制,保证临界区可以被上限bound个线程锁访问。

3. 把Semaphore当锁用

当信号量的上限为1时,即可将Semaphore当做锁来使用,如下:

...
BoundedSemaphore semaphore = new BoundedSemaphore(1);
...
semaphore.take();
try{
    //业务代码
} finally {
    semaphore.release();
}
...

必须注意,release 方法应当在 finally 块中被执行。这样可以保在关键区域的代码抛出异常的情况下,信号也一定会被释放。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值