c++11多线程编程(六):事件处理

来源:互联网 发布:hadoop编程 编辑:程序博客网 时间:2024/06/07 04:01
本节讨论在多线程环境下的事件处理。
有时,线程需要等待某事件发生,比如一个条件变为true,或者某任务被另一个线程完成。
例如,我们创建一个基于网络的应用程序,处理如下的任务:
1、与处理器进行一些握手操作;2、从xml文件load数据;3、处理从xml文件load的数据.

可以发现,任务1不依赖其他的任务,而任务3则依赖于任务2,这意味着任务1和任务2可以由不同的线程并行运行,以提升程序性能。


因此,让我们将其分解成一个多线程的应用程序
现在,它包含2个线程,线程1的任务是:
·与服务器进行握手操作·等待线程2从xml获取的数据·处理从xml获取的数据


线程2的任务是:
·从xml获取数据·通知另一个线程,即等待消息



在上图中,线程1处理一些操作,然后等待event发生,这event是 “数据是否成功获取”,一旦线程1收到该event,那么它将对数据进行处理。
当线程1忙于处理握手机制时,线程2并行地获取数据。
当线程2成功从xml处获取数据后,它将通过对event发信号来通知线程1。
当event发出信号时,线程1将继续处理数据。

实现方式
选项1:
创建一个默认为false的boolean型全局变量,在线程2中将其设为true,线程1将会循环检测其值,一旦该值被设为true,线程1将会继续处理数据,
由于它是一个由两个线程共享的全局变量,需要使用mutex锁进行同步。
代码如下:

#include <iostream>#include <thread>#include <mutex>class Application{    std::mutex m_mutex;    bool m_bDataLoaded;public:Application(){m_bDataLoaded = false;}void loadData(){        //使该线程sleep 1秒std::this_thread::sleep_for(std::chrono::milliseconds(1000));std::cout<<"Load Dada from Xml"<<std::endl;        //锁定数据std::lock_guard<std::mutex> guard(m_mutex);        //flag设为true,表明数据已加载m_bDataLoaded = true;}void mainTask(){std::cout<<"Do some Handshaking"<<std::endl;        //获得锁        m_mutex.lock();        //检测flag是否设为true        while (m_bDataLoaded != true) {            //释放锁            m_mutex.unlock();            //sleep 100ms            std::this_thread::sleep_for(std::chrono::milliseconds(100));            //获取锁            m_mutex.lock();        }        m_mutex.unlock();        //处理加载的数据        std::cout<<"Do Processing On loaded Data"<<std::endl;    }};int main(){Application app;std::thread thread_1(&Application::mainTask, &app);std::thread thread_2(&Application::loadData, &app);thread_2.join();thread_1.join();return 0;}

输出:

Do some HandshakingLoad Dada from XmlDo Processing On loaded Data

该方法存在以下缺陷:
为了检测变量,线程将会持续获取-释放锁,这样会消耗CPU周期并且使线程1变慢,因为它需要获取相同的锁来更新bool变量。
因此,显然我们需要一个更好的实现机制,如某种方式,线程1可以通过等待event信号来阻塞,另一个线程可以通知该event并使线程1继续。这将会有相同的CPU周期,并有更好的性能。

选项2:
我们可以使用条件变量来实现,条件变量是一种用于在2个线程之间进行信令的事件,一个线程可以等待它得到信号,其他的线程可以给它发信号。
下一节会详细说明这个条件变量,并使用条件变量来解决问题。

原创粉丝点击