1. 经典的生产者和消费者问题
【例5-18】 理解【例5-14】一个生产和一个消费的实现例子, 用信号量机制编程实现经典的生产者和消费者问题:
多个生产者和多个消费者共享一个n 个大小的缓冲区(设为数组buf[n]), 设缓冲区一次只能一个人使用。 生产者的工作是不断放入产品, 消费者则是不断地取出产品, 程序模拟实现应不能出现空已满而生产者还能放入, 无产品而消费者能够取出的错误。
该经典问题的算法很多操作系统书籍中可查, 它们之间的同步关键是要通过合适的信号量处理, 在缓冲区全空或全满时能控制住不该执行的错误逻辑, 而且阻塞的进程可以被另一个有同步关系的进程的释放操作唤醒。 实现代码如下。
其执行结果如下。
生产者能通过对e 的申请才能向下执行, 而放入产品后会释放f 信号, 消费者反之。从执行结果看同步关系符合逻辑。 为了体现同步代码的关键控制作用, 执行程序时, 可以在初始时分别给两种不同的状态: 全满(e=0、 f=n)和全空(e=n、 f=0), 对比不同的运行效果, 体验同步控制的作用。
注意执行结果, 观察模拟的放入和取出操作的输出语句(运行结果中标识有∗), 20个子进程产生后, 每个都放入了一次产品后, in++或out++后的输出却都是1。 这是因为fork 的克隆性操作, 每个新产生的进程在自己内存中实际上都有这两个计数变量的副本,他们的加1 操作是加在了各自内存空间的副本变量上, 并没有累加。 让生产者间、 消费者间能够共享计数变量, 此实验体现出了进程间的共享不容易。(www.daowen.com)
我们通过内存映射, 给所有的子进程共享了某内存地址(代码中标识有#), 这样大家对共享变量的计数才有了累加。 而为了防止修改的相互影响, 对共享内存的操作多人间要互斥, 所以对shminaddr 变量的操作要写在互斥信号内。
2. 黑白棋轮流下子问题
【例5-19】 两个选手下棋, 下棋规则是不规定谁占先手, 哪方先落子就先下, 然后依次轮流下棋。 用POSIX 信号量实现线程同步模拟双方间的同步关系。 其代码如下。
其执行结果如下。
调整模拟的sleep 时间, 可以测试不同的先后顺序。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。