Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/150.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ boost::wait和boost::condition是否必须共享同一个互斥对象 boost::条件变量cond; 互斥互斥; //螺纹#1 对于(;;) { D*D=nullptr; 而(cb.pop(d))//cb是一个循环缓冲区,manage在内部是自己的互斥锁/锁 { //…用d做点什么 } boost::唯一的锁(互斥锁); 条件等待(互斥); } //螺纹#2 而(1) { getchar(); 对于(int i=0;i_C++_Multithreading_Boost_C++11 - Fatal编程技术网

C++ boost::wait和boost::condition是否必须共享同一个互斥对象 boost::条件变量cond; 互斥互斥; //螺纹#1 对于(;;) { D*D=nullptr; 而(cb.pop(d))//cb是一个循环缓冲区,manage在内部是自己的互斥锁/锁 { //…用d做点什么 } boost::唯一的锁(互斥锁); 条件等待(互斥); } //螺纹#2 而(1) { getchar(); 对于(int i=0;i

C++ boost::wait和boost::condition是否必须共享同一个互斥对象 boost::条件变量cond; 互斥互斥; //螺纹#1 对于(;;) { D*D=nullptr; 而(cb.pop(d))//cb是一个循环缓冲区,manage在内部是自己的互斥锁/锁 { //…用d做点什么 } boost::唯一的锁(互斥锁); 条件等待(互斥); } //螺纹#2 而(1) { getchar(); 对于(int i=0;i,c++,multithreading,boost,c++11,C++,Multithreading,Boost,C++11,我想知道我的数据容器是否有自己的锁以避免数据竞争,另一方面boost::wait是否可以使用boost文档指定的锁/互斥机制 否则,thread1就是consummer,如果我只有一个线程“consumme”,那么wait所需的锁似乎有点多余,不是吗 编辑:我不关心缺少的更新。当我收到更新时,我用收到的数据更新对象。我只需要更新,不需要所有udpate如果您的环形缓冲区的push和pop功能是线程安全的,那么您不需要额外的同步 如果有多个读卡器,则可以使用读卡器/写卡器锁来启用多个线程同时读取。

我想知道我的数据容器是否有自己的锁以避免数据竞争,另一方面boost::wait是否可以使用boost文档指定的锁/互斥机制

否则,thread1就是consummer,如果我只有一个线程“consumme”,那么wait所需的锁似乎有点多余,不是吗


编辑:我不关心缺少的更新。当我收到更新时,我用收到的数据更新对象。我只需要更新,不需要所有udpate

如果您的环形缓冲区的
push
pop
功能是线程安全的,那么您不需要额外的同步


如果有多个读卡器,则可以使用读卡器/写卡器锁来启用多个线程同时读取。

通常,应使用条件变量来表示线程之间共享的条件,以便以线程安全的方式访问该条件。但是,在等待时需要解锁互斥锁,以便其他线程可以更改条件。有关队列的示例,请参见


在您的情况下,您已经有一个线程安全容器。将Condition变量放在容器中并让它使用其互斥锁不是更好吗?

condvar必须使用保护数据的互斥锁(好的,不完全是,下面更精确),否则您将错过更新:

boost::condition_variable cond;
boost::mutex mutex;

//thread #1
for(;;)
{
    D * d = nullptr;

    while( cb.pop(d) )  //cb is a circular buffer and manage is own mutex/lock internally
    {
        //...do something with d
    }
    boost::unique_lock<boost::_mutex> lock( mutex );
    cond.wait( mutex );
}

//thread #2
while(1)
{
    getchar();

    for( int i = 0 ; i < 1000 ; ++i )
    {
        cb.push(new D(i));      //one producer so no lock required

        cond.notify_one();     // no lock required here ?
    }
}
要避免这种情况,您必须在消费者中:

  • mutex
  • 确认不满足该条件
  • cond.wait(互斥)
  • 返回验证条件(互斥锁再次锁定)
  • 在producer中,您必须:

  • mutex
  • 使条件为真(即cb.push())
  • cond.notify\u one()
  • 现在您终于可以解锁互斥锁了
  • 因此,它不一定是保护数据的锁,但您必须在最后一次检查和等待消费者以及设置条件和通知生产者时进行锁定

    另一方面,实际上可以创建不需要与锁配合的通知机制。“为信号注册”和“等待信号”需要单独的操作,后者在第一次信号出现后立即返回(您检查它们之间的条件)。然而,我在任何可移植线程库中都没有看到这种机制


    编辑:另一方面,信号量可能更适合管理消息队列。具有反映队列中项目数的信号量。你每次
    向上
    向下
    它,然后每次
    弹出
    (或者只是将它嵌入队列本身,这样如果队列为空,那么
    pop
    只需等待某个东西出现即可)。

    你可以拥有任意数量的锁,但你会得到竞争条件 除非
    pop
    push
    都受到与
    等待
    通知
    (并且在 决定等待和实际等待)。标准成语是:

    producer             consumer
    
                         while(cb.pop()) ...;
    cb.push();
    cond.notify_one();
                         cond.wait(); // OOPS. I missed the notification!
    
    这更复杂,我看不出你能从中得到什么。只是 使用已知工作可靠的常用模式

    FWIW:你的代码充满了竞争条件:对于初学者来说:
    pop
    在线程1中失败,存在上下文切换,线程2执行
    推送
    通知
    ,然后返回线程1,执行
    等待
    。 然后等待,尽管队列中有东西

    我可以补充一点,几乎从来没有任何理由支持这样的类型 循环缓冲区来管理自己的互斥锁。粒度是 太低了。例外情况是,如果pop指令实际上一直等到 有些东西在那里,即(基于
    std::deque
    ):

    T*循环缓冲::推送(标准::自动插入)
    {
    boost::unique_lock l(myMutex);
    myQueue.push_back(in.get());
    in.release();//只有在成功推回之后!
    myCondition.notify_all();
    }
    std::auto_ptr CircularBuffer::pop()
    {
    boost::unique_lock l(myMutex);
    while(myQueue.empty()){
    myCondition.wait();
    }
    std::auto_ptr result(myQueue.front());
    myQueue.pop_front();
    返回结果;
    }
    
    (注意在接口中使用了
    auto_ptr
    。一旦提供程序 将对象传递到队列中时,该对象不再具有访问权限

    您似乎正在使用支持C++0x的编译器(通过使用
    nullptr
    可以看出),但您仍然使用Boost中的线程库。为什么?我使用的是msvc2010,它不支持C++0X EntrelyMy data container是静态的,在我的上下文中,我有多个生产者和一个消费者。因此消费者是线程安全的,而procuder不是,所以我只需要一个互斥体来保护对生产者中容器的访问。但我的疑问是,在这种情况下,互斥的正确用法是什么?我是否应该使用相同的互斥来等待和等待生产者,还是不一定使用?我实际上认为必须这样做。解锁和开始等待必须是原子的,否则您可能会错过更新。@stefaanc:是的,您可能是对的,如果我在容器中放入条件变量,比如在push-an中放入notify_one,会更好
    //  thread #1
    // ...
    {
        boost::unique_lock<boost::mutex> lock( mutex );
        while ( !cb.pop( d ) )
            cond.wait( mutex );
    }
    // process d
    
    
    //  thread #2
    // ...
    {
        boost::unique_lock<boost::mutex> lock( mutex );
        cb.push( new D(i) );
        cond.notify_one();
    }
    
    boost::unique_lock<boost::mutex> lock( mutex );
    while ( cb.pop( d ) ) {
        lock.unlock();
        //  process d
        lock.lock();
    }
    cond.wait( mutex );
    
    T* CircularBuffer::push( std::auto_ptr<T> in )
    {
        boost::unique_lock<boost::mutex> l( myMutex );
        myQueue.push_back( in.get() );
        in.release();  // Only after the push_back has succeeded!
        myCondition.notify_all();
    }
    
    std::auto_ptr<T> CircularBuffer::pop()
    {
        boost::unique_lock<boost::mutex> l( myMutex );
        while ( myQueue.empty() ) {
            myCondition.wait();
        }
        std::auto_ptr<T> result( myQueue.front() );
        myQueue.pop_front();
        return result;
    }