模拟记录型信号量解决生产者-消费者问题
作为java多线程的经典例题之一的生产者消费者问题。
- 用记录型信号量解决生产者-消费者问题
- 假定在生产者和消费者之间的公用缓冲池中具有n个缓冲区,
这时可利用互斥信号量mutex实现诸进程对缓冲池的互斥使用;
• 利用信号量empty和full分别表示缓冲池中空缓冲区和满缓冲
区的数量。
• 又假定这些生产者和消费者相互等效,只要缓冲池未满,生
产者便可将消息送入缓冲池;
• 只要缓冲池未空,消费者便可从缓冲池中取走一个消息。
参考代码:
int in = 0, out = 0;//in: 输入指针, out: 输出指针;
item buffer[n];//n个缓冲区组成的数组;
semaphore mutex = 1, full = 0, empty = n;
//mutex: 互斥信号量, 生产者进程和消费者进程都只能互斥访问缓冲区;
//full: 资源信号量, 满缓冲区的数量;
//empty: 资源信号量, 空缓冲区的数量;//信号量不允许直接参与运算, 故都要定义;
//生产者程序;
void Producer() {
do {
生产者生产一个产品nextp;
wait(empty);//申请一个空缓冲区;
wait(mutex);//申请临界资源;
buffer[in] = nextp;//将产品添加到缓冲区;
in = (in + 1) % n;//类似于循环队列;
signal(mutex);//释放临界资源;
signal(full);//释放一个满缓冲区;
} while (TRUE);
}
//消费者程序;
void Producer() {
do {
wait(full);//申请一个满缓冲区;
wait(mutex);//申请临界资源;
nextc = buffer[out];//将产品从缓冲区取出;
out = (out + 1) % n;//类似于循环队列;
signal(mutex);//释放临界资源;
signal(empty);//释放一个空缓冲区;
消费者将一个产品nextc消费;
} while (TRUE);
}
java实现及解析;
public class Main {
public static void main(String[] args) {
Main main=new Main();
Buffer[] buffers=new Buffer[bufferSize];
//给缓冲区编号:
for(int i=0;i<bufferSize;i++) {
buffers[i]=main.new Buffer();
buffers[i].setNumber(i+1);
}
Producer p=main.new Producer(buffers);
p.start();
Customer c=main.new Customer(buffers);
c.start();
}
/**
定义生产者,消费者共享的临界资源缓冲区的数量。
Semaphore也是一个线程同步的辅助类,可以维护当前访问自身的线程个数,并提供了同步机制。它其中的常用方法:
参数为许可证数量。
void acquire():从此信号量获取一个许可,在提供一个许可前一直将线程阻塞,否则线程被中断。(相当于加锁)
void release():释放一个许可,将其返回给信号量。(相当于释放锁)
int availablePermits():返回此信号量中当前可用的许可数。
boolean hasQueuedThreads():查询是否有线程正在等待获取。
*/
private static int bufferSize=20;//缓冲区数量
private Semaphore mutex=new Semaphore(1);//互斥信号量
//初始值为bufferSize个许可证,也就是说缓冲区一个东西也没有放
private Semaphore empty=new Semaphore(bufferSize);//空缓冲区,
private Semaphore full=new Semaphore(0);//满缓冲区
int in=0,out=0;
//定义wait信号方法:加锁
public int WAIT(Semaphore semaphore) {
try {
semaphore.acquire();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return semaphore.availablePermits();
}
//定义signal信号方法:释放锁
public int SIGNAL(Semaphore semaphore) {
semaphore.release();
return semaphore.availablePermits();
}
/**
* 共享缓冲区
* */
class Buffer{
private int number;//缓冲区编号
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number=number;
}
public void in() {
System.out.println("放入第"+number+"号缓冲区");
}
public void out() {
System.out.println("从第"+number+"号缓冲区拿出");
}
}
/**
* 生产者
*/
class Producer extends Thread{
Buffer[] buffers;
public Producer(Buffer[] buffers) {
this.buffers=buffers;
}
@Override
public void run() {
while(true) {
WAIT(empty);
WAIT(mutex);
buffers[in].in();
in=(in+1)%bufferSize;
SIGNAL(mutex);
SIGNAL(full);
}
}
}
/**
* 消费者
*/
class Customer extends Thread{
Buffer[] buffers;
public Customer(Buffer[] buffers) {
this.buffers=buffers;
}
@Override
public void run() {
while(true) {
WAIT(full);
WAIT(mutex);
buffers[out].out();
out=(out+1)%bufferSize;
SIGNAL(mutex);
SIGNAL(empty);
}
}
}
}
运行结果: