草庐IT

c++ - boost::wait 和 boost::condition 是否必须共享相同的互斥对象

coder 2024-02-12 原文

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 ?
    }
}

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

否则,线程 1 是消费者,如果我只有一个线程“消费”,那么 wait 所需的锁似乎有点多余,不是吗?

编辑:我不关心丢失的更新。当我收到更新时,我用收到的数据更新一个对象。我只想要更新鲜的更新,而不是所有更新

最佳答案

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

//  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();
}

尝试在线程 #1 中的 pop 上循环更复杂,至少 如果你想在 d 的处理过程中释放锁。你需要 像这样的东西:

boost::unique_lock<boost::mutex> lock( mutex );
while ( cb.pop( d ) ) {
    lock.unlock();
    //  process d
    lock.lock();
}
cond.wait( mutex );

它更复杂,我看不出你能从中得到什么。只是 使用已知的可靠工作的常用模式。

FWIW:您的代码充满了竞争条件:对于初学者:pop 线程 1 失败,有一个上下文切换,线程 2 执行 pushnotify,然后返回到执行 cond.wait 的线程 1。 等待,尽管队列中有东西。

我可能会补充说,几乎没有任何理由支持像这样的类型 循环缓冲区来管理自己的互斥锁。粒度是 太低。异常(exception)情况是弹出指令实际上等到 那里有东西,即(基于 std::deque):

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;
}

(注意接口(interface)中auto_ptr的使用。一旦提供者有 将对象传入队列,它不再有访问权限 它。)

关于c++ - boost::wait 和 boost::condition 是否必须共享相同的互斥对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6923641/

有关c++ - boost::wait 和 boost::condition 是否必须共享相同的互斥对象的更多相关文章

  1. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  2. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

  3. ruby-on-rails - 按天对 Mongoid 对象进行分组 - 2

    在控制台中反复尝试之后,我想到了这种方法,可以按发生日期对类似activerecord的(Mongoid)对象进行分组。我不确定这是完成此任务的最佳方法,但它确实有效。有没有人有更好的建议,或者这是一个很好的方法?#eventsisanarrayofactiverecord-likeobjectsthatincludeatimeattributeevents.map{|event|#converteventsarrayintoanarrayofhasheswiththedayofthemonthandtheevent{:number=>event.time.day,:event=>ev

  4. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  5. ruby-on-rails - 如何验证非模型(甚至非对象)字段 - 2

    我有一个表单,其中有很多字段取自数组(而不是模型或对象)。我如何验证这些字段的存在?solve_problem_pathdo|f|%>... 最佳答案 创建一个简单的类来包装请求参数并使用ActiveModel::Validations。#definedsomewhere,atthesimplest:require'ostruct'classSolvetrue#youcouldevencheckthesolutionwithavalidatorvalidatedoerrors.add(:base,"WRONG!!!")unlesss

  6. Ruby 写入和读取对象到文件 - 2

    好的,所以我的目标是轻松地将一些数据保存到磁盘以备后用。您如何简单地写入然后读取一个对象?所以如果我有一个简单的类classCattr_accessor:a,:bdefinitialize(a,b)@a,@b=a,bendend所以如果我从中非常快地制作一个objobj=C.new("foo","bar")#justgaveitsomerandomvalues然后我可以把它变成一个kindaidstring=obj.to_s#whichreturns""我终于可以将此字符串打印到文件或其他内容中。我的问题是,我该如何再次将这个id变回一个对象?我知道我可以自己挑选信息并制作一个接受该信

  7. ruby - 检查数组是否在增加 - 2

    这个问题在这里已经有了答案:Checktoseeifanarrayisalreadysorted?(8个答案)关闭9年前。我只是想知道是否有办法检查数组是否在增加?这是我的解决方案,但我正在寻找更漂亮的方法:n=-1@arr.flatten.each{|e|returnfalseife

  8. ruby - 通过 ruby​​ 进程共享变量 - 2

    我正在编写一个gem,我必须在其中fork两个启动两个webrick服务器的进程。我想通过基类的类方法启动这个服务器,因为应该只有这两个服务器在运行,而不是多个。在运行时,我想调用这两个服务器上的一些方法来更改变量。我的问题是,我无法通过基类的类方法访问fork的实例变量。此外,我不能在我的基类中使用线程,因为在幕后我正在使用另一个不是线程安全的库。所以我必须将每个服务器派生到它自己的进程。我用类变量试过了,比如@@server。但是当我试图通过基类访问这个变量时,它是nil。我读到在Ruby中不可能在分支之间共享类变量,对吗?那么,还有其他解决办法吗?我考虑过使用单例,但我不确定这是

  9. ruby-on-rails - 如果 Object::try 被发送到一个 nil 对象,为什么它会起作用? - 2

    如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象

  10. ruby-on-rails - 未在 Ruby 中初始化的对象 - 2

    我在Rails工作并有以下类(class):classPlayer当我运行时bundleexecrailsconsole然后尝试:a=Player.new("me",5.0,"UCLA")我回来了:=>#我不知道为什么Player对象不会在这里初始化。关于可能导致此问题的操作/解释的任何建议?谢谢,马里奥格 最佳答案 havenoideawhythePlayerobjectwouldn'tbeinitializedhere它没有初始化很简单,因为你还没有初始化它!您已经覆盖了ActiveRecord::Base初始化方法,但您没有调

随机推荐