Semaphore使用以及原理
- 介绍
- 原理
- 使用场景
- 使用方法
- Demo
介绍
Semaphore(信号量)是一种用于控制并发访问资源的机制。它可以用于多线程或多进程环境中,用于保护共享资源的访问,避免竞争条件和死锁。
原理
- Semaphore维护一个计数器,表示可用的资源数量。
- 每当一个线程(或进程)需要访问资源时,它必须先申请Semaphore。
- 如果Semaphore的计数器大于0,表示有可用的资源,线程可以继续执行,并将计数器减1。
- 如果Semaphore的计数器等于0,表示没有可用的资源,线程将被阻塞,直到有资源可用。
- 当一个线程使用完资源后,必须释放Semaphore,使计数器加1,表示资源可用。
使用场景
- 限制资源的并发访问:可以设置Semaphore的计数器为资源数量,每个线程需要访问资源时,必须先申请Semaphore,如果计数器为0,则线程将被阻塞,直到有资源可用。
- 控制线程的执行顺序:可以使用Semaphore来控制线程的执行顺序,例如,设置Semaphore的计数器为1,只允许一个线程执行,其他线程将被阻塞。
使用方法
-
导入Semaphore类:在代码中导入Semaphore类,例如 import java.util.concurrent.Semaphore;
-
创建Semaphore对象:使用 new 关键字创建Semaphore对象,并指定初始的可用资源数量。例如, Semaphore semaphore = new Semaphore(5); 表示创建一个初始计数器为5的Semaphore对象
-
申请资源:当一个线程需要访问资源时,可以调用 acquire() 方法来申请Semaphore。例如, semaphore.acquire(); 表示线程申请Semaphore,如果计数器大于0,则计数器减1,否则线程将被阻塞。
-
使用资源:线程成功申请到Semaphore后,可以继续执行访问资源的逻辑。
-
释放资源:当一个线程使用完资源后,必须调用 release() 方法释放Semaphore。例如, semaphore.release(); 表示线程释放Semaphore,计数器加1。
Demo
import java.util.concurrent.Semaphore;
public class SemaphoreExample {
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(2); // 创建Semaphore对象,初始计数器为2
// 创建多个线程
for (int i = 0; i < 5; i++) {
Thread thread = new Thread(() -> {
try {
semaphore.acquire(); // 申请Semaphore
System.out.println("Thread " + Thread.currentThread().getId() + " acquired the semaphore.");
// 访问资源的逻辑
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
semaphore.release(); // 释放Semaphore
System.out.println("Thread " + Thread.currentThread().getId() + " released the semaphore.");
}
});
thread.start();
}
}
}
在上述示例中,创建了一个Semaphore对象,初始计数器为2。然后创建了5个线程,每个线程在执行前先申请Semaphore,如果计数器大于0,则继续执行,否则被阻塞。线程执行完逻辑后,释放Semaphore,计数器加1。
这样就可以通过Semaphore来控制并发访问资源的数量,避免资源竞争和死锁的问题。