生产者消费者之关于boost::condition的用法

boost线程库的基本用法这篇文章有介绍到
http://www.cppblog.com/fwxjj/archive/2006/12/04/15975.html

我这里只讨论boost::condition在reader/writer模式中的一些注意点

首先我们看只有一个reader/一个writer的情形

#include <boost/thread/mutex.hpp>
#include <boost/thread/condition.hpp>
#include <boost/thread/thread.hpp>
#include <boost/thread/xtime.hpp>
#include <iostream>

int number;
boost::mutex m;
boost::condition not_full;
boost::condition not_empty;

void writer()
{
    while (1) {
        boost::mutex::scoped_lock sl(m);
        if (number == 5) {
            not_full.wait(m);
        }
        ++number;
        std::cout << "after w: " << number << std::endl;
        not_empty.notify_one();
    }
}

void reader()
{
    while (1) {
        boost::mutex::scoped_lock sl(m);
        if (number == 0) {
            not_empty.wait(m);       
        }
        --number;
        std::cout << "after r: " << number << std::endl;
        not_full.notify_one();
    }
}

void main()
{
    boost::thread trd1(&writer);
    boost::thread trd2(&reader);
    trd1.join();
    trd2.join();
}

运行之后程序一切如常,0-5的一些数字会打印出来。

但是当另外一个write加入战局的时候,情况变得有些微妙的不同,如果我们只是在main里面加入一个writer,其他部分保持不变的话,你会看到一些错误的数字出现:

void main()
{
    boost::thread trd1(&writer);
    boost::thread trd11(&writer);
    boost::thread trd2(&reader);
    trd1.join();
    trd11.join();
    trd2.join();
}

究其原因是:在reader->notify_one之后并在socped_lock解锁之前,在not_full上等待的writer A被唤起,然后reader解锁,此时可能另外一个writer B先获得锁而直接增加了number。在writeB 解锁后, writerA获得锁,但此时not_full条件已经被破坏。所以一种做法是再次检查该条件,也就是这样:

while (number == 5) {
    not_full.wait(m);
}

对于多write或多reader的情形也是一样都需要以一个while循环进行conditiond的复检:完整的代码如下

#include <boost/thread/mutex.hpp>
#include <boost/thread/condition.hpp>
#include <boost/thread/thread.hpp>
#include <boost/thread/xtime.hpp>
#include <iostream>

int number;
boost::mutex m;
boost::condition not_full;
boost::condition not_empty;

void writer()
{
    while (1) {
        boost::mutex::scoped_lock sl(m);
        while (number == 5) {
            not_full.wait(m);
        }
        ++number;
        std::cout << "after w: " << number << std::endl;
        not_empty.notify_one();
    }
}

void reader()
{
    while (1) {
        boost::mutex::scoped_lock sl(m);
        while (number == 0) {
            not_empty.wait(m);       
        }
        --number;
        std::cout << "after r: " << number << std::endl;
        not_full.notify_one();
    }
}

void main()
{
    boost::thread trd1(&writer);
    boost::thread trd11(&writer);
    boost::thread trd2(&reader);
    boost::thread trd22(&reader);
    trd1.join();
    trd11.join();
    trd2.join();
    trd22.join();
}

时间: 2024-08-03 08:56:21

生产者消费者之关于boost::condition的用法的相关文章

[多线程] 生产者消费者模型的BOOST实现

说明 如果 使用过程中有BUG 一定要告诉我:在下面留言或者给我邮件(sawpara at 126 dot com) 使用boost::thread库来实现生产者消费者模型中的缓冲区! 仓库内最多可以存放 capacity 个产品. 条件变量 condition_put 标记是否可以往仓库中存放一个产品. 条件变量 condition_get 标记是否可以从仓库中取出一个产品. 互斥量 mutexer 用于保证当前仓库只有一个线程拥有主权. 实现 #include <queue> #inclu

Condition线程通信_生产者消费者案例

①Condition 接口描述了可能会与锁有关联的条件变量. 这些变量在用 法上与使用 Object.wait 访问的隐式监视器类似,但提供了更强大的 功能. 需要特别指出的是,单个 Lock 可能与多个 Condition 对象关 联. 为了避免兼容性问题,Condition 方法的名称与对应的 Object 版 本中的不同.② 在 Condition 对象中,与 wait.notify 和 notifyAll 方法对应的分别是 await.signal 和 signalAll.③ Condi

生产者消费者模式(转)

本文转载自博文系列架构设计:生产者/消费者模式.文中对原文格式进行了稍加整理. 概述 今天打算来介绍一下“生产者/消费者模式”,这玩意儿在很多开发领域都能派上用场.由于该模式很重要,打算分几个帖子来介绍.今天这个帖子先来扫盲一把.如果你对这个模式已经比较了解,请跳过本扫盲帖,直接看下一个帖子(关于该模式的具体应用) . 看到这里,可能有同学心中犯嘀咕了:在四人帮(GOF)的23种模式里面似乎没听说过这种嘛!其实GOF那经典的23种模式主要是基于OO的(从书名<Design Patterns: E

C++11 生产者消费者

下面是一个生产者消费者问题,来介绍condition_variable的用法.当线程间的共享数据发生变化的时候,可以通过condition_variable来通知其他的线程.消费者wait 直到生产者通知其状态发生改变,Condition_variable是使用方法如下: ·当持有锁之后,线程调用wait ·wait解开持有的互斥锁(mutex),阻塞本线程,并将自己加入到唤醒队列中 ·当收到通知(notification),该线程从阻塞中恢复,并加入互斥锁队列(mutex queue) 线程被

Thinking in Java---线程通信+三种方式实现生产者消费者问题

前面讲过线程之间的同步问题:同步问题主要是为了保证对共享资源的并发访问不会出错,主要的思想是一次只让一个线程去访问共享资源,我们是通过加锁的方法实现.但是有时候我们还需要安排几个线程的执行次序,而在系统内部线程的调度是透明的,没有办法准确的控制线程的切换.所以Java提供了一种机制来保证线程之间的协调运行,这也就是我们所说的线程调度.在下面我们会介绍三种用于线程通信的方式,并且每种方式都会使用生产者消费者问题进行检验. 一.使用Object类提供的线程通信机制 Object类提供了wait(),

从生产者消费者窥探线程同步(下)

欢迎转载,转载请注明出处.尊重他人的一丢丢努力,谢谢啦! 阅读本篇之前,如果你还没有看过从生产者消费者窥探线程同步(上) ,那不妨先戳一下,两篇一起嚼才更好呢. 上一篇分析了使用BlockQueue和synchronized来实现生产者消费者模式.这一篇来看一下其他的实现,闲言少叙. (3)Lock实现 核心:Lock的用法中规中矩,有点类似于非静态同步方法,只是前者是对lock对象显式加锁,而后者是对当前对象隐式加锁. 我相信大多数人在第一次接触Lock锁的时候,内心都会有这样的疑惑:明明提供

架构设计:生产者/消费者模式

[0]:概述 今天打算来介绍一下“生产者/消费者模式”,这玩意儿在很多开发领域都能派上用场.由于该模式很重要,打算分几个帖子来介绍.今天这个帖子先来扫盲一把.如果你对这个模式已经比较了解,请跳过本扫盲帖,直接看下一个帖子(关于该模式的具体应用). 看到这里,可能有同学心中犯嘀咕了:在四人帮(GOF)的23种模式里面似乎没听说过这种嘛!其实GOF那经典的23种模式主要是基于OO的(从书名<Design Patterns: Elements of Reusable Object-Oriented S

POSIX 使用互斥量和条件变量实现生产者/消费者问题

boost的mutex,condition_variable非常好用.但是在Linux上,boost实际上做的是对pthread_mutex_t 和pthread_cond_t的一系列的封装.因此通过对原生态的POSIX 的mutex,cond的生成者,消费者的实现,我们可以再次体会boost带给我们的便利. 1. 什么是互斥量 互斥量从本质上说是一把锁,在访问共享资源前对互斥量进行加锁,在访问完成后释放互斥量上的锁.对互斥量进行加锁以后,任何其他试图再次对互斥量加锁的线 程将会被阻塞直到当前线

生产者/消费者模式之深入理解

#include <windows.h> #include <iostream> const unsigned short SIZE_OF_BUFFER = 2; //缓冲区长度 unsigned short ProductID = 0; //产品号 unsigned short ConsumeID = 0; //将被消耗的产品号 unsigned short in = 0; //产品进缓冲区时的缓冲区下标 unsigned short out = 0; //产品出缓冲区时的缓冲区