一.信号量的理解.
1.简介
信号量(Semaphore)多运用于多线程代码中,用来控制可同时访问某个资源的线程数,是java.util.curcurrent下的一个工具类.
2.具体理解.
信号量
对于第一次接触的小伙伴可能会有些蒙蔽,应该怎样去理解呢?
其实可以把信号量理解成一个停车场,里面的车位数就是控制访问的线程数,每一个车就是一个线程,当某辆车想要进入时,需要从门口获得许可排队进入.
能否获取到许可取决于停车场中的车位空闲数,如果有空位,则可获得许可进入,否则在门口排队等待.
当里面的有车出来时,当前空位数+1,有车获得许可进入时,当前空位数-1.
互斥锁
互斥锁可以理解为一个厕所隔间,每次只能允许一个人进入,进去之后就会上锁,当出来之后才允许其他人进入.其实本质就是强行将并行变为串行,以达到线程安全的目的.
二.二者的区别与应用场景.
1.锁每次只能一个线程进入,多了不行,少了也不行,但是信号量却可以控制任意个线程,可以是0个,也可以是很多个.
2.使用信号量可以让一个线程作为一个管理者去控制某个资源是否可以被其他线程锁访问(如果不理解这句话可以看后面的信号量实战).而使用锁只能让线程作为一个参与者来控制某个资源不被其他线程锁访问(该情况就是当前线程占有锁时,其他线程只能阻塞等待)
三.信号量实战.
本例举的是LeetCode多线程编程第三题.
题目在这LeetCode多线程第三题
这里简单说一下解题思路:
用输出0的线程来控制输出奇数和偶数的线程,奇数和偶数初始信号量都为0,也就是刚开始都获取不到资源,只能等待,直到输出0的线程执行release()方法,这时可获取一个信号,去执行输出奇数或偶数的代码.
代码如下:
class ZeroEvenOdd {
private int n;
public ZeroEvenOdd(int n) {
this.n = n;
}
//新建三个初始信号量
Semaphore zeroSemaphore=new Semaphore(1);
//刚开始信号量为0,也就是不能获取到资源,待release后才可获得资源
Semaphore evenSemaphore=new Semaphore(0);
Semaphore oddSemaphore=new Semaphore(0);
public void zero(IntConsumer printNumber) throws InterruptedException {
for(int i=0;i<n;i++){
zeroSemaphore.acquire();
printNumber.accept(0);
//判断输出奇数还是偶数
if((i&1)==0){
oddSemaphore.release();
}else{
evenSemaphore.release();
}
}
}
public void even(IntConsumer printNumber) throws InterruptedException {
for(int i=2;i<=n;i+=2){
evenSemaphore.acquire();
printNumber.accept(i);
zeroSemaphore.release();
}
}
public void odd(IntConsumer printNumber) throws InterruptedException {
for(int i=1;i<=n;i+=2){
oddSemaphore.acquire();
printNumber.accept(i);
zeroSemaphore.release();
}
}
}