Semaphore信号量

概要

Semaphore当前在多线程环境下被扩放使用,操作系统的信号量是个很重要的概念,在进程控制方面都有应用。Java 并发库的Semaphore可以很轻松完成信号量控制,Semaphore可以控制某个资源可被同时访问的个数,通过 acquire()获取一个许可,如果没有就等待,而release()释放一个许可。用来控制资源同时访问个数

​ 以一个停车场运作为例。假设停车场只有三个车位,一开始三个车位都是空的。这时如果同时来了五辆车,看门人允许其中三辆不受阻碍的进入,然后放下车拦,剩下的车则必须在入口等待,此后来的车也都不得不在入口处等待。这时,有一辆车离开停车场,看门人得知后,打开车拦,放入一辆,如果又离开两辆,则又可以放入两辆,如此往复。

构造函数

Semaphore提供了一个带有boolean参数的构造方法,true代表公平锁,false代表非公平锁,默认实现是非公平锁。

1
2
public Semaphore(int permits); // 创建具有给定许可数的非公平Semaphore
public Semaphore(int permits, boolean fair); //创建具有给定许可数的公平(true)或非公平(false) Semaphore

普通方法

1
2
3
4
5
public void acquire() //从此信号量获取一个许可,在提供一个许可前一直将线程阻塞,否则线程被中断
public void acquire(int permits) //从此信号量获取给定数目的许可,在提供这些许可前一直将线程阻塞,或者线程已被中断
public void release() //释放一个许可,将可用的许可数增加1
public void release(int permits) //释放给定数目的许可,将其返回到信号量
public boolean isFair() //如果此信号量的公平设置为true,则返回 true

停车案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
package com.zsr.test.Semaphore;
import java.util.concurrent.Semaphore;
class Car implements Runnable {
private final Semaphore parkingspace;
private int carNo;
/**
* @param parkingspace
* @param carNo
*/
public Car(Semaphore parkingspace, int carNo) {
this.parkingspace = parkingspace;
this.carNo = carNo;
}
public void run() {
try {
parkingspace.acquire();
parking();
Thread.sleep(300);
parkingspace.release();
leaving();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void parking() {
System.out.println(String.format("%d号车泊车", carNo));
}
private void leaving() {
System.out.println(String.format("%d号车离开车位", carNo));
}
}
public class ParkingCars {
private static final int NUMBER_OF_CARS = 5;
private static final int NUMBER_OF_PARKING_SPACE = 3;
public static void main(String[] args) throws InterruptedException {
Semaphore parkingSpace = new Semaphore(NUMBER_OF_PARKING_SPACE, true);
for (int carNo = 1; carNo <= NUMBER_OF_CARS; carNo++) {
new Thread(new Car(parkingSpace, carNo)).start();
}
Thread.sleep(3000);
/*
* 输出还有几个可以用的资源数
*/
System.out.println(parkingSpace.availablePermits() + " 个停车位可以用!");
}
}

输出结果:

1
2
3
4
5
6
7
8
9
10
11
2号车泊车
1号车泊车
3号车泊车
2号车离开车位
4号车泊车
3号车离开车位
1号车离开车位
5号车泊车
4号车离开车位
5号车离开车位
3 个停车位可以用!

热评文章