前言
信号量,即Semaphore,表示可用资源的个数。
在实际生活中,也会有与Semaphore相同的情况,比如停车场的空位数,当有车开进去时,空位 数就会减1,当有车开出停车场后,空位数就会加1。
方法介绍
在Semaphore中,有两个处理资源的方法,acpuire和release。
acpuire可以用来获取资源,release可以用来释放资源,现假设Semaphor中由100个资源,每执行一次acquire,就会消耗一个资源,每执行一次release,就会释放一个资源,当将100个资源全部申请完后,若再继续申请就会进行阻塞等待。
Semaphore与线程安全的关系
上述我们知道,当将Semaphore中的资源申请完后,就会进行阻塞等待,当Semaphore中只有1个资源时,若一个线程获取到这个资源,那么另一个资源再次申请时就会进行阻塞等待,直到第一个线程释放掉这个资源,第二个线程才能获取到这个资源,从而继续执行,那么此时第一个线程就会进行阻塞等待,这样就可以保证线程安全问题。
现有如下代码:
public class Demo1 {
private static int count;
public static void main(String[] args) throws InterruptedException {
Thread thread1 = new Thread(() -> {
for (int i = 0; i < 10000; i++) {
count++;
}
});
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 10000; i++) {
count++;
}
});
thread1.start();
thread2.start();
thread1.join();
thread2.join();
System.out.println(count);
}
}
由于线程安全问题,最后count的值大概率不为20000;,为了解决上面的线程安全问题 ,除了使用synchronized进行加锁,还可以使用Semaphore,并且Semaphore中的资源量为1,代码如下:
package Thread;
import java.util.concurrent.Semaphore;
public class SemaphoreDemo {
private static int count;
public static void main(String[] args) throws InterruptedException {
Semaphore semaphore = new Semaphore(1);//申请一个资源量
Thread thread1 = new Thread(() -> {
for (int i = 0; i < 10000; i++) {
try {
semaphore.acquire();//获取资源
count++;
semaphore.release();;//释放资源
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
});
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 10000; i++) {
try {
semaphore.acquire();//获取资源
count++;
semaphore.release();//释放资源
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
});
thread1.start();
thread2.start();
thread1.join();
thread2.join();
System.out.println(count);
}
}
最后的结果如下:
多次运行的结果都是20000