Boost条件变量可以用来实现线程同步,它必须与互斥量配合使用。使用条件变量实现生产者消费者的简单例子如下,需要注意的是cond_put.wait(lock)是在等待条件满足。如果条件不满足,则释放锁,将线程置为waiting状态,继续等待;如果条件满足,则重新获取锁,然后结束wait,继续向下执行。
#include <stdio.h>
#include <process.h>
#include <windows.h>
#include <iostream>
#include <string>
#include <stack>
using namespace std;
#include <boost/assign.hpp>
#include <boost/typeof/typeof.hpp>
#include <boost/thread.hpp>
using namespace boost;
using namespace this_thread;
using namespace boost::assign;
//一个生产者,两个消费者,四个缓冲区
mutex muConsole;//互斥访问缓冲区
//缓冲区对象
class CBuffer{
private:
mutex muBuffer;
condition_variable_any condPutInto;
condition_variable_any condGetFrom;
stack<int> stkBuffer;
int iCapacity;//缓冲区的数量
int iUnRead;//可读数据
private:
bool IsFull(){ return (iUnRead == iCapacity);}
bool IsEmpty(){ return (iUnRead == 0);}
public:
CBuffer(int capacity){ iCapacity = capacity; iUnRead = 0;}
void PutInto(int data){
{
mutex::scoped_lock oLock(muBuffer);
//如果条件不满足,释放锁,阻塞线程
while(IsFull()){condPutInto.wait(oLock);}
stkBuffer.push(data);
++iUnRead;
}
condGetFrom.notify_one();
}
void GetFrom(int& data){
{
mutex::scoped_lock oLock(muBuffer);
//如果条件不满足,释放锁,阻塞线程
while(IsEmpty()){condGetFrom.wait(oLock);}
--iUnRead;
data = stkBuffer.top(); stkBuffer.pop();
}
condPutInto.notify_one();
}
};
//四个缓冲区的内存池
CBuffer oBuffer(4);
//生产者线程
void ProducerProc(int times, string name){
for(int i = 0; i < times; i++){
oBuffer.PutInto(i);
muConsole.lock();
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED);
cout << name << " put " << i << " into buffer." << endl;
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
muConsole.unlock();
}
}
//消费者线程
void ConsumerProc(int times, string name){
int iData = -1;
for(int i = 0; i < times; i++){
oBuffer.GetFrom(iData);
muConsole.lock();
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN);
cout << name << " get " << iData << " from buffer." << endl;
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
muConsole.unlock();
}
}
void main()
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
//创建线程对象,启动线程函数
thread oProducer(ProducerProc, 8, "Producer");
thread oConsumer1(ConsumerProc, 4, "Consumer1");
thread oConsumer2(ConsumerProc, 4, "Consumer2");
//等待所有线程结束执行
oProducer.join();
oConsumer1.join();
oConsumer2.join();
cout << endl << endl << "所有子线程都已经结束执行" << endl << endl;
}