• ACE线程管理机制并发控制(3)


    ACE Condition类属

    ACE Condition类属(条件变量)提供风格与互斥体、读者/作者锁和计数信号量不同的锁定机制。当持有锁的线程在临界区执行代码时,这三种机制让协作线程进行等待。相反,条件变量通常被一个线程用于使自己等待,直到一个涉及共享数据的条件表达式到达特定的状态。当另外的协作线程指示共享数据的状态已发生变化,调度器就唤醒一个在该条件变量上挂起的线程。于是新唤醒的线程重新对它的条件表达式进行求值,如果共享数据已到达合适状态,就恢复处理。

    ACE线程库提供一个叫作Condition的类来可移植地在C++包装类中实现条件变量语义。定义方式如下:
    ACE_Thread_Mutex mutex;
    ACE_Condition<ACE_Thread_Mutex> cond(mutex);

    该对象有两个常用方法。

    1. signal()
      向使用该条件变量的其它线程发送满足条件信号。
    2. wait()
      查询是否满足条件,如果满足,则继续往下执行;如果不满足条件,主线程就等待在此条件变量上。条件变量随即自动释放互斥体,并使主线程进入睡眠。

    条件变量总是与互斥体一起使用。这是一种可如下描述的一般模式:

    while( expression NOT TRUE ) wait on condition variable;

    条件变量不是用于互斥,往往用于线程间的协作,下面例子演示了通过条件变量实现线程协作。

    #include "ace/Thread.h"
    #include "ace/Synch.h"

    #include <iostream>
    using namespace std;

    ACE_Thread_Mutex mutex;
    ACE_Condition<ACE_Thread_Mutex> cond(mutex);

    void* worker(void *arg)
    {
        ACE_OS::sleep(2);        //保证eater线程的cond.wait()在worker线程的cond.signal()先执行
        mutex.acquire();
        ACE_OS::sleep(1);
        cout<<endl<<"produce"<<endl;
        cond.signal();
        mutex.release();
        return NULL;
    }

    void* eater(void *arg)
    {
        mutex.acquire();
        cond.wait();
        cout<<endl<<"eat"<<endl;
        mutex.release();
        return NULL;
    }

    int main(int argc, char *argv[])
    {
        ACE_Thread::spawn((ACE_THR_FUNC)worker);
        ACE_OS::sleep(1);
        ACE_Thread::spawn((ACE_THR_FUNC)eater);

        while(true)
            ACE_OS::sleep(10);

        return 0;
    }

    这个例子中,首先创建了一个生产者线程worker和一个消费者线程eater,消费者线程执行比生产者快,两个线程不加限制并发执行会导致先消费,后生产的情况(只是加互斥锁也不能很好的解决,以为无法保证生产者一定先获得互斥体)。所以这里通过条件变量的通知方式保证线程的顺序执行:

    1. 消费者线程获取互斥体,等待条件满足(生产者生产了食品)。同时释放互斥体,进入休眠状态。
    2. 生产者获取互斥体(虽然是消费者先获取的互斥体,但消费者调用的wait函数会释放消费者的互斥体),生产商品后,通过条件变量发送信号(调用signal函数)通知消费者生产完成,结束生产过程,释放互斥体。
    3. 消费者收到信号后,重新获取互斥体,完成消费过程。

         

    使用条件变量的注意事项:

    1. 条件变量必须和互斥体一起使用,也就是说使用前必须加锁(调用互斥体acquire函数),使用完后需释放互斥体。

    条件变量中的wait()和signal()成对使用的话,必须保证wait()函数在signal()之前执行,这样才能保证wait()能收到条件满足通知,不至于一直等待下去,形成死锁(worker线程中的第一句话就是起的这个作用)。

  • 相关阅读:
    Git 一些常用命令
    Opengl VS2008开发环境
    用 HTML5 给 iPad,iPhone 打造速度超快的应用_HTML5研究小组
    理解CSS3 transform中的Matrix(矩阵) « 张鑫旭鑫空间鑫生活
    Google Dremel 原理 如何能 3 秒分析 1PB 开源中国社区
    Perl:过滤注释
    HTML5 History API实现无刷新跳转 蓝飞技术部落格 —— 关注前沿,追求卓越。
    OPENGL编程指南
    Perl : Quantifier follows nothing in regex; marked by
    .js文件无法运行的方法
  • 原文地址:https://www.cnblogs.com/TianFang/p/581854.html
Copyright © 2020-2023  润新知