引言
在多線程編程中,控制對共享資源的訪問是一個關鍵問題。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
,可以方便地限制同時訪問某個資源的線程數量,從而實現資源池、限流器等功能。