1. 先看几个semaphore的写法,可以看到semaphore的acquire和release都是和wait和notify相关的
// 设置最大信号量 public class SemaphoreMax { private int signals = 0; private int bound = 0; public SemaphoreMax(int bound){ this.bound = bound; } public synchronized void take() throws InterruptedException{ // 信号量达到最大,那么就进入等待,后面的那个回去执行, // 然后等待执行完成再去释放信号量,然后去唤醒,唤醒之后又有新的线程进入 // ,就会使得信号量增加,然后又进入等待 while(this.signals == bound){ wait(); } this.signals ++; this.notify(); } public synchronized void release() throws InterruptedException{ while(this.signals == 0){ wait(); } this.signals --; this.notify(); } }
在上面的简单semaphore例子中,有一个最大的信号量,有一个统计当前信号量的signal
从take方法中对应java中的acquire方法,表示获取一个信号量,当我们获取到一个信号量之后,先判断当前是否信号量已经被使用完毕了,如果使用完了,那么就让所有线程进行等待,如果没有到达最大信号量,,那么就唤醒一个线程进行操作。
在release方法中对应java中的release方法,表示释放一个信号量,当调用这个方法之后会去判断当前的信号量是否为0,也就是是否有可用的信号量,如果有可用的信号量,那么就会在下面减去一个可用的信号量,然后唤醒一个线程,这样在下次我们take获取的时候就会有一个线程能够进入take方法然后去判断当前对象所持有的信号量是否达到最大。
2. 看一个用信号量控制绘图的示例:
上面是对两个量进行比较,然后并且有一个标志来判断当前的排序比较是否继续进行,如果run为false,也就是点击了暂停,那么就获取一个信号量,让当前线程进入等待状态,因为信号量只有一个信号。
当点击继续运行的时候就释放一个信号量,然后设置run为false,并且释放一个信号量,然后这个信号量就会在下面的比较中进行一次,然后再次acquire一个信号量,然后这个信号量执行完了之后因为已经达到了最大的信号量,所以当前线程就会处于wait状态,这样绘制就会暂停,然后通过再次点击这个上面的方法设置run为false,并且release一个信号量,这样线程继续运行到判断run的比较上面。