以下内容讲的是这样一个例子:
现有类A,
其结构如下所示:
class A: { .... 一些数据成员和成员函数; .... dataType data; 主函数 process(dataType& data,...);//data需要其他线程送入,而且根据系统需求,只要data更新,process便执行一次。 };
现在我们想让类A在开启线程后和其他线程实现通信,怎么办呢?
首先通信必须有一块共同的数据缓存区,比如B线程要往A线程传数据,基本思想是B线程有数据后 放入一个数据缓存区里,然后后A再从这个数据缓存区中读取数据。既然数据缓存区是两个线程共用的,那么数据缓存区就必须加锁。加锁为的是避免这样一个情况:B线程正在往数据缓存区写,而恰好此时,A又从数据缓存去读。
有了这个想法之后,现在我们对类A进行改造。
class A: { ... 一些数据成员和成员函数; ... dataType data; 主函数 process(dataType& data,...);//data需要其他线程送入 void run();//在类里定义一个死循环,用来执行此类的功能函数(方法) void ReceiveDataFromOtherThread(dataType& datain);//定义接收数据的函数 std::queue<dataType> dataCache; //通信数据缓存区 std::mutex dataCacheMutex; //通信数据缓存区的锁 std::condition_variable cond_; //线程的条件变量 };
其中,接收数据的函数是这样定义的
void A::ReceiveDataFromOtherThread(dataType& datain) { std::unique_lock<mutex> lock(dataCacheMutex); dataCache.push(datain);//其他线程往缓存区放数据 cond_.notify_one(); }
run函数是整个类的主函数,这样定义:
void A::run() { while(1) { { std::unique_lock<mutex> lock(dataCacheMutex); while(dataCache.size()<0) cond_.wait(lock); data=dataCache.back();//本线程从缓存区读取数据 dataCache.pop(); } ... process(data,....); ... } }
我们加了这么多东西的作用就是专用于线程通信的。
类改造完成,怎样通讯呢?现在举一个最简单的例子,比如在主线程(main函数所在线程)和新定义的线程完成通讯:
main() { A *a=new A(...);//实例化类A std::thread * threadA=new thread(&A::run,a);//用类A的run函数开启一个线程 主线程循环 { dataType DATA ... a->ReceiveDataFromOtherThread(DATA);//主线程往threadA线程发送数据 ... } }
想要其他线程和threadA进行通讯也很简单,就是把对象a的指针传入要通信的线程,在那个线程指定的地方调用
a->ReceiveDataFromOtherThread(DATA);//其他线程往threadA线程发送数据