模拟AND信号量解决生产者-消费者问题
问题描述:
AND型信号量和记录型信号量原理大致相同。
想较与记录型信号量,AND型信号量主要做了以下改动:
用Swait(empty,mutex)来代替wait(empty)和wait(mutex);
• 用Ssignal(mutex,full)来代替signal(mutex)和signal(full);
• 用Swait(full,mutex)代替wait(full)和wait(mutex);
• 用Ssignal(mutex,empty)代替Signal(mutex)和
Signal(empty)。
记录型信号量解决生产者消费者问题请点如下链接:
https://blog.csdn.net/qq_45273552/article/details/109054767
参考代码(原语):
Var mutex,empty,full:semaphore:=1,n,0;
buffer:array[0,...,n-1]of item;
in,out:integer:=0,0;
begin
parbegin
proceducer:begin
repeat
.
.
.
producer an item nextp;
.
.
.
wait(empty);
wait(mutex);
buffer(in):=nextp;
in:=(in+1)mod n;
signal(mutex);
signal(full);
until false;
end
consumer:begin
repeat
wait(full);
wait(mutex);
nextc:=buffer(out);
out:=(out+1)mod n;
signal(mutex);
signal(empty);
consumer the item in neXtg;
until false;
end
parend
end
java代码实现:
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Main {
private static int bufferSize=20;//缓冲区数量
private Semaphore mutex=new Semaphore(1);//互斥信号量
private Semaphore empty=new Semaphore(bufferSize);//空缓冲区
private Semaphore full=new Semaphore(0);//满缓冲区
int in=0,out=0;
/*
Lock锁,可以得到和 synchronized一样的效果,即实现原子性、有序性和可见性。
相较于synchronized,Lock锁可手动获取锁和释放锁、可中断的获取锁、超时获取锁。
它是一个接口,两个直接实现类:
ReentrantLock(重入锁),
ReentrantReadWriteLock(读写锁)。
此处用的可重入锁 ReentrantLock
与synchronized相比,重入锁有着显式的操作过程,开发人员必须手动的指定何时加锁(调用lock方法),何时释放锁(调用unlock方法)。因此,重入锁对逻辑的控制性要好于synchronized
*/
/*
Condition接口介绍:
任意一个Java对象,都拥有一组监视器方法(定义在Object类中),主要包括wait,notify,notifyAll方法,这些方法与synchornized关键字相配合,可以实现等待/通知模式。
Condition接口也提供了类似的Object的监视器方法,与Lock配合可以实现等待/通知模式。(具体用法请自行搜索)
*/
//可重入锁和条件变量
static Lock lock = new ReentrantLock();
static Condition condition = lock.newCondition();
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();
}
//定义wait信号方法:加锁
public void SWAIT(Semaphore...list) {
lock.lock();
//如果资源不足,就挂起线程,并将线程插入到condition的队列中
while (true) {
int count=0;
for (Semaphore semaphore:list){
if(semaphore.availablePermits()>0){
count++;
}
}
if(count == list.length){
break;
}
try {
condition.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
for (Semaphore semaphore:list){
try {
semaphore.acquire();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
lock.unlock();
}
//定义signal信号方法:释放锁
public void SSIGNAL(Semaphore...list) {
try {
lock.tryLock(1, TimeUnit.SECONDS);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
for (Semaphore semaphore:list){
semaphore.release();
}
//唤醒等待队列中的一个线程
condition.signal();
lock.unlock();
}
/**
* 共享缓冲区
* */
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) {
SWAIT(empty,mutex);
buffers[in].in();
in=(in+1)%bufferSize;
SSIGNAL(mutex,full);
}
}
}
/**
* 消费者
*/
class Customer extends Thread{
Buffer[] buffers;
public Customer(Buffer[] buffers) {
this.buffers=buffers;
}
@Override
public void run() {
while(true) {
SWAIT(full,mutex);
buffers[out].out();
out=(out+1)%bufferSize;
SSIGNAL(mutex,empty);
}
}
}
}
运行结果: