利用记录型信号量机制: wait(s), signal(s)解决进程同步问题


wait(s) 等价与P操作, signal(s)等价于V操作
下面采用信号量机制中的 记录型信号量来解决生产者-消费者问题

生产者-消费者问题

操作系统

int in = 0, out = 0;
item buffer[n];
semaphore mutex = 1, empty = n, full = 0;
void procuder() {
  do {
      procuder an item nextp;
      ...
      wait(empty);//表示空缓冲区-1;
      wait(mutex);//数据缓冲区互斥访问,关闭访问;
      buffer[in] = nextp;
      in = (in+1) % n;
      signal(mutex);//打开访问
      signal(full);//满缓冲区加+1
  } while (true);
}

void consumer() {
   do {
       wait(full);//判断是否有满缓冲区,满缓冲区-1
       wait(mutex);
       nextc = buffer[out];
       out = (out+1) % n;
       signal(mutex);
       siganl(empty);//空缓冲区+1
       consumer the item in nextc;
       ....
   } while (true);
}

void main() {
  cobegin
    producer(); consumer();
  coend
}

生产者-消费者问题(Java语言实现)

import java.util.concurrent.*;
import java.util.*;

/**
 * 使用信号量计数器Semaphore,
 */
public class SemaphoreTest {
    // 互斥信号量,实现对缓存区的互斥访问
    Semaphore mutex = new Semaphore(1);
    // 同步信号量,表示空缓冲区数量
    Semaphore empty = new Semaphore(10);
    // 同步信号量,表示产品的数量,即非空缓冲区的数量
    Semaphore full = new Semaphore(0);
    // 存储载体
    ArrayDeque<Object> items = new ArrayDeque<>();
    // 当前生产数量
    static int putNum = 0;
    // 当前消费数量
    static int getNum = 0;

    public static void main(String[] args) {
        SemaphoreTest manager = new SemaphoreTest();
        Thread producer = new Thread(() -> {
            while (true) {
                manager.put(new Object());
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        producer.setName("生产者线程0 ");
        producer.start();
        Thread customer = new Thread(() -> {
            while (true) {
                manager.take();
//                     让生产速度大于消费速度
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        customer.setName("消费者线程0 ");
        customer.start();
    }

    // 生产
    public void put(Object item) {
        try {
            // 确保当前还有空间剩余,empty进行减一
            empty.acquire();
            // 互斥访问临界区
            mutex.acquire();
            // 增加库存
            items.addLast(item);
            putNum++;
            System.out.println(Thread.currentThread().getName() + "正在生产第" + putNum + "个产品");
            // 非空信号量加一
            full.release();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            mutex.release();
        }
    }

    // 消费
    public Object take() {
        try {
            // 确保当前有产品可拿,full进行减一
            full.acquire();
            // 互斥访问临界区
            mutex.acquire();
            // 减少库存
            Object item = items.removeFirst();
            getNum++;
            System.out.println(Thread.currentThread().getName() + "正在消费第" + getNum + "个产品");
            // 空信号量加一
            empty.release();
            return item;
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            // 退出临界区
            mutex.release();
        }
        return null;
    }

}

爸爸妈妈洗水果,儿子女儿吃水果问题

问题描述:爸爸专向盘中放苹果,妈妈专向盘中放橘子,儿子专等吃盘里的橘子,女儿专等吃盘里的苹果。只要盘子空,爸爸妈妈可向盘中放水果,仅当盘中有自己需要的水果时,儿子或女儿可从中取出,请给出他们四人之间的同步关系,并用PV操作实现四人正确活动的程序。。使用p、v操作来完成父亲、妈妈、儿子、女儿的同步行为模拟。

semaphore putmutex = 1, getmutex = 0;
semaphore empty = 1, apple = 0, orange = 0;
void father() {
  do {
    wait(putmutex);
    apple++;
    empty--;
    signal(putmutex);
  } while (true);
}
void mother() {
  do {
    wait(putmutex);
    orange++;
    empty--;
    signal(putmutex);
  } while (true);
}
void son() {
   do {
     wait(getmutex);
     orange--;
     empty++;
     signal(getmutex);
   } while (true);
}
void daughter() {
  do {
    wait(getmutex);
    apple--;
    empty++;
    signal(getmutex);
  } while (true);
}
void main() {
  cobegin
    father(); mother(); son(); daughter();
  coend
}

此外 ,可参考java的实现:http://www.cnblogs.com/zyp4614/p/6555530.html

司机,售票员问题

问题:
司机开车,售票员售票。当售票员将门关上的时候司机才可以开车,当司机将车到站停下的时候,售票员才可以打开车门。

对S1(门): 门有两个状态,开和关。售票员将门关上之后,应该将门的操作权给司机(因为只有司机到站了才能停车)。因此0为门开着状态。
对S2(车):两个状态,开车行驶和到站停车。当车开的时候,需要申请车的资源,即用wait,则车在停着的时候状态为1,行驶时状态为0.
司机:开车,正常行驶,到站停车
售票员:关门,售票,开门

S1表示是否允许司机启动汽车;S1 = 1表示可以启动,S2 = 0表示不能启动。
S2表示是否允许售票员关车门;S2 = 1表示允许售票员关车门,S2 = 0表示不允许售票员关车门。

semaphore s1 = 1, s2 = 0;
void driver() {
  do {
    wait(s1);// P(S1)
    开车;
    正常行驶;
    到站停车;
    signal(s2);//V(S2)
  } while (true);
}
void seller() {
  do {
    关门;
    signal(s1);// V(S1)
    售票;
    wait(S2);//P(S2)
    开车门;
    上下乘客;
  } while (true);
}
void main() {
  cobegin
    driver(); seller();
  coend
}

可参考博客: http://m.blog.csdn.net/Y_215/article/details/53467517
其他有关:进程同步,进程互斥,信号量机制,管程机制可参考:
https://flyjhs.blog.csdn.net/article/details/115717651

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值