持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第1天
一、介绍
Semaphore是 java.util.Concurrent下的一个类
Semaphore翻译过来是信号量的意思,它的作用是控制多个线程对同一个资源的访问线程数量。比如在停车场停车,里面有10个车位,当这10个车位被停满的时候其他的车只能等待(堵塞)里面有车驶出(release)然后再进入。
Semaphore可以用做流量控制,主要是共用资源的应用场景。
二、常用方法
voidacquire()从该信号量获取许可证,阻止直到可用,或线程为 interrupted 。voidacquire(int permits)从该信号量获取给定数量的许可证,阻止直到所有可用,否则线程为 interrupted 。voidacquireUninterruptibly()从这个信号灯获取许可证,阻止一个可用的。voidacquireUninterruptibly(int permits)从该信号量获取给定数量的许可证,阻止直到所有可用。intavailablePermits()返回此信号量中当前可用的许可数。voidrelease()释放许可证,将其返回到信号量。voidrelease(int permits)释放给定数量的许可证,将其返回到信号量。booleantryAcquire()从这个信号量获得许可证,只有在调用时可以使用该许可证。booleantryAcquire(int permits)从这个信号量获取给定数量的许可证,只有在调用时全部可用。- acquire():获取一个访问令牌,获取令牌就可以对资源进行访问,如果没有获取成功就阻塞等待。
- release():在获取玩资源时归还令牌,给其他的线程使用。
- tryacquire():获取一个访问令牌,获取令牌就可以对资源进行访问,如果没有获取成功不阻塞等待而是返回一个false。
- availablePermits():获取许可证的总数
三、Semaphore的构造
编辑
传入一个permits来表示当前信号量允许拥有的最大许可数量。
四、实例
public class SemaphoreDemo {
public static int num = 0;
public static void main(String[] args) throws InterruptedException {
Semaphore semaphore = new Semaphore(1);
for (int i = 0; i < 2; i++) {
new Thread(() -> {
try {
semaphore.acquire();
for (int j = 0; j < 5000; j++) {
num++;
}
semaphore.release();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}).start();
}
Thread.sleep(3000);
System.out.println(num);
}
}
这里我创建了两个匿名线程分别去执行5000次对num的++操作,这里的运行结果时10000而没有出现线程竞争出现的加数原子性问题,是因为这里我限制了许可证只有一个当一个线程拿到并且在执行完后才能归还许可让下一个阻塞等待的线程拿到去执行。
最后的Thread.sleep(300)是让主线程等待一下我们创建的两个线程执行完再输出num的值。
如果有多线程的问题可以访问我的博客主页欢迎讨论!