引言
在多线程编程中,控制对共享资源的访问是一个关键问题。Java 提供了多种同步机制来解决这个问题,其中 Semaphore
是一种常用的工具类,用于限制可以同时访问某个资源的线程数。本文将详细介绍 Semaphore
的概念、使用方法和实际应用场景。
1. Semaphore 概述
Semaphore
是 java.util.concurrent
包中的一个类,用于控制同时访问某个特定资源的线程数量。它维护了一组许可(permits),线程在访问资源前必须先获得许可,访问结束后再释放许可。Semaphore
可以用于实现资源池、限流器等功能。
2. Semaphore 的基本使用
2.1 初始化
Semaphore
可以通过两种方式进行初始化:
// 初始化一个具有指定许可数量的 Semaphore
Semaphore semaphore = new Semaphore(permits);// 初始化一个具有指定许可数量,并指定是否为公平模式的 Semaphore
Semaphore semaphore = new Semaphore(permits, fair);
permits
:初始的许可数量。fair
:如果为true
,则Semaphore
按照 FIFO(先进先出)原则分配许可,否则按照默认的非公平模式。
2.2 主要方法
acquire()
:获取一个许可,如果没有可用的许可,则阻塞直到有许可可用。acquire(int permits)
:获取指定数量的许可。tryAcquire()
:尝试获取一个许可,立即返回,不阻塞。tryAcquire(int permits)
:尝试获取指定数量的许可。release()
:释放一个许可。release(int permits)
:释放指定数量的许可。
3. 示例代码
以下是一个使用 Semaphore
控制对共享资源访问的示例代码,模拟了一个停车场的场景,限制了同时停放的车辆数量。
import java.util.concurrent.Semaphore;public class ParkingLot {private final Semaphore semaphore;public ParkingLot(int slots) {this.semaphore = new Semaphore(slots);}public void parkCar(String carName) {try {System.out.println(carName + " is trying to enter the parking lot.");semaphore.acquire();System.out.println(carName + " has entered the parking lot.");// 模拟停车时间Thread.sleep((long) (Math.random() * 10000));} catch (InterruptedException e) {e.printStackTrace();} finally {System.out.println(carName + " is leaving the parking lot.");semaphore.release();}}public static void main(String[] args) {final int parkingSlots = 3;final ParkingLot parkingLot = new ParkingLot(parkingSlots);for (int i = 1; i <= 10; i++) {final String carName = "Car-" + i;new Thread(() -> parkingLot.parkCar(carName)).start();}}
}
4. Semaphore 的实际应用场景
- 资源池:控制对有限资源的并发访问,如数据库连接池、线程池等。
- 限流器:限制某些操作的并发执行数量,防止过载。
- 多路复用器:实现多路复用机制,控制对多个资源的访问。
- 同步工具:协调多线程之间的交互,确保按顺序访问某些资源。
5. Semaphore 的优缺点
优点
- 灵活性:可以灵活控制同时访问资源的线程数量。
- 简单易用:API 简单明了,容易理解和使用。
- 公平性:支持公平模式,保证线程按顺序获取许可。
缺点
- 性能开销:在高并发场景下,频繁的许可获取和释放操作可能带来一定的性能开销。
- 死锁风险:如果许可获取和释放操作不正确,可能导致死锁。
6. Semaphore 的扩展
- 超时机制:
tryAcquire(long timeout, TimeUnit unit)
方法可以尝试在指定时间内获取许可,如果超时则返回false
。 - 多许可控制:
Semaphore
可以同时控制多个许可,通过acquire(int permits)
和release(int permits)
方法进行多许可的获取和释放。
结论
Semaphore
是 Java 并发包中一个强大的工具类,用于控制对共享资源的并发访问。通过使用 Semaphore
,可以方便地限制同时访问某个资源的线程数量,从而实现资源池、限流器等功能。