对信号量只能实施三种操作:
1.
初始化(initialize),也叫做建立(create)
2.
等信号(wait),也可叫做挂起(pend)
3.
给信号(signal)或发信号(post)
分类:
整型信号量(integer
semaphore):信号量是整数
记录型信号量(record
semaphore):每个信号量s除一个整数值s.value(计数)外,还有一个进程等待队列s.L,其中是阻塞在该信号量的各个进程的标识
二进制信号量(binary
semaphore):只允许信号量取0或1值
每个信号量至少须记录两个信息:信号量的值和等待该信号量的进程队列。它的类型定义如下:(用类PASCAL语言表述)
semaphore
= record
value: integer;
queue:
^PCB;
end;
其中PCB是 进程控制块,是 操作系统为每个进程建立的 数据结构。
s.value>=0时,s.queue为空;
s.value<0时,s.value的 绝对值为s.queue中等待进程的个数;
JDK的并发包就给我提供了一个类似的信号量类——Semaphore 。
生产者-消费者问题
import java.util.concurrent.Semaphore; class Signs{ static Semaphore empty=new Semaphore(10); //信号量:记录仓库空的位置 static Semaphore full=new Semaphore(0); //信号量:记录仓库满的位置 static Semaphore mutex=new Semaphore(1); //临界区互斥访问信号量(二进制信号量),相当于互斥锁。 } class Producer implements Runnable{ public void run(){ try { while(true){ Signs.empty.acquire(); //递减仓库空信号量 Signs.mutex.acquire(); //进入临界区 System.out.println("生成一个产品放入仓库"); Signs.mutex.release(); //离开临界区 Signs.full.release(); //递增仓库满信号量 Thread.currentThread().sleep(100); } } catch (InterruptedException e) { e.printStackTrace(); } } } class Consumer implements Runnable{ public void run(){ try { while(true){ Signs.full.acquire(); //递减仓库满信号量 Signs.mutex.acquire(); System.out.println("从仓库拿出一个产品消费"); Signs.mutex.release(); Signs.empty.release(); //递增仓库空信号量 Thread.currentThread().sleep(1000); } } catch (InterruptedException e) { e.printStackTrace(); } } } public class Test{ public static void main(String[] args) { new Thread(new Producer()).start(); new Thread(new Consumer()).start(); } }
进一步可参考:http://blog.csdn.net/ljsspace/article/details/6702093
哲学家进餐问题
在1965年,Dijkstra提出并解决了一个他称之为哲学家进餐的同步问题。从那时起,每个发明新的同步原语的人都希望通过解决哲学家进餐间题来展示其同步原语的精妙之处。这个问题可以简单地描述:五个哲学家围坐在一张圆桌周围,每个哲学家面前都有一碟通心面,由于面条很滑,所以要两把叉子才能夹住。相邻两个碟子之间有一把叉子。
哲学家的生活包括两种活动:即吃饭和思考。当一个哲学家觉得饿时,他就试图去取他左边和右边的叉子。如果成功地获得两把叉子,他就开始吃饭,吃完以后放下叉子继续思考。
更多:
http://hxraid.iteye.com/blog/739265
多线程信号量 Semaphore使用,布布扣,bubuko.com
原文:http://www.cnblogs.com/youxin/p/3586577.html