注意:这里的三个方法均是原子操作。在Java SDK里,信号量是由java.util.concurrent.Semaphore实现的,Semaphore可以保证方其都是原子操作。并且在Java SDK并发包中,down()和up()对应的是acquire()和release()方法。
参考下面代码感受一下信号量模型:
class Semaphore{
// 计数器
int count;
// 等待队列
Queue queue;
// 初始化操作
Semaphore(int c){
this.count=c;
}
//
void down(){
this.count--;
if(this.count<0){
// 将当前线程插入等待队列
// 阻塞当前线程
}
}
void up(){
this.count++;
if(this.count<=0) {
// 移除等待队列中的某个线程 T
// 唤醒线程 T
}
}
}
正如开篇介绍信号量可以控制线程的执行,相当于互斥锁一样,控制单一线程对临界资源的访问。而限号量正是通过计数器来实现互斥规则的。
如下代码:
static int count;
// 初始化信号量
static final Semaphore s
= new Semaphore(1);
// 用信号量保证互斥
static void addOne() {
s.acquire();
try {
count+=1;
} finally {
s.release();
}
}
信号量具体如何实现互斥?
Semaphore有一个独特的功能,就是可以允许多个线程访问一个临界区。这里就通过“快速实现一个限流器”来说明;
解决方法:在上一个例子中我们将计数器初始化为1,表示只允许一个线程进入临界区,现在我们将计数器设置为对象池中的对象个数N,表明在同一个时刻允许N个线程可以同时进入到临界区,就可以解决限流问题了;
思考:信号量在在执行release()方法后如果满足唤醒其他线程条件就会去唤醒一个线程继续执行,这里为什么不能去唤醒所有线程呢?
因篇幅问题不能全部显示,请点此查看更多更全内容