1.信号量用来累计唤醒的次数,从而不会产生notify信号丢失的问题。信号量也要指定初始信号的大小,acquire()方法将信号量的值减一,如果信号量的值小于等于零,那么调用线程会阻塞。而release()方法将信号量加一,并且不会产生阻塞。关键:信号量的取值,判断,修改以及可能发生的阻塞这一系列操作都是原子操作。
2.信号量可以用来控制同时访问某个特定资源的操作数量,或者同时执行某个指定操作的数量,还可以用来实现某种资源池,或者对容器加边界。使用初始信号为1的信号量可以实现互斥锁。
3.信号量的acquire()默认从等待池中随机选择一个阻塞的线程,并且是可闯入的,即刚好有一个资源并且有一个线程刚好调用acquire(),那么它有能获得资源而不是优先选择在等待池中的线程。
但是在初始化信号量时可以设置参数fairness为true,这样选择线程时将采用FIFO的顺序并且不可闯入。
4.例子:
1.实现生产者消费者问题
public class SemaphoreExample {
private int size; // 存放产品的槽的数目
private int[] array;// 存放产品的容器
private Semaphore mutex;// 互斥量,控制每次只能有一个线程访问数组,也可以用synchronized
private Semaphore empty; // 记录空槽数目
private Semaphore full; // 记录满槽数目
private Random rand;
public SemaphoreExample(int size) {
this.size = 0;
empty = new Semaphore(size);
full = new Semaphore(0);
mutex = new Semaphore(1);
rand = new Random();
array = new int[size];
}
public void prodecter() throws InterruptedException {
int item = rand.nextInt(100);
// 获得添加元素的许可
empty.acquire();
// 获得访问数组的许可
mutex.acquire();
array[size++] = item;
System.out.println("add " + item);
// 立即释放互斥锁
mutex.release();
// 添加元素后,增加许可
full.release();
}
public void constomer() throws InterruptedException {
// 获得取出元素的许可
full.acquire();
// 获得访问数组的许可
mutex.acquire();
System.out.println("get " + array[--size]);
// 立即释放锁
mutex.release();
// 取出元素后,增加许可
empty.release();
}
public static void main(String[] args) throws InterruptedException {
SemaphoreExample obj = new SemaphoreExample(5);
CountDownLatch start = new CountDownLatch(1);
CountDownLatch canStart = new CountDownLatch(10);
// 五个生产者线程
for (int i = 0; i < 5; i++) {
new Thread(new Runnable() {
public void run() {
try {
canStart.countDown();
// 等待开关开始
start.await();
obj.prodecter();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
}
// 五个消费者线程
for (int i = 0; i < 5; i++) {
new Thread(new Runnable() {
public void run() {
try {
canStart.countDown();
// 等待开关开始
start.await();
obj.constomer();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
}
//等待10个线程都开始运行
canStart.await();
start.countDown();
}
}
result:
add 27
add 34
get 34
add 67
get 67
add 71
get 71
add 78
get 78
get 27