list :: empty()多线程行为?

Ann*_*inn 9 c++ optimization multithreading race-condition stdlist

我有一个列表,希望不同的线程从中获取元素。为了避免在列表为空时锁定保护该列表的互斥锁,请empty()在锁定之前进行检查。

如果对电话的呼叫在list::empty()100%的时间内都不正确,则可以。我只想避免崩溃或中断并发list::push()list::pop()调用。

我是否可以肯定地认为VC ++和Gnu GCC有时只会empty()出错并且没有比这更糟的了?

if(list.empty() == false){ // unprotected by mutex, okay if incorrect sometimes
    mutex.lock();
    if(list.empty() == false){ // check again while locked to be certain
         element = list.back();
         list.pop_back();
    }
    mutex.unlock();
}
Run Code Online (Sandbox Code Playgroud)

Nat*_*ica 10

如果对电话的呼叫在list::empty()100%的时间内都不正确,则可以。

不,这不好。如果在某种同步机制(锁定互斥锁)之外检查列表是否为空,则将发生数据争用。进行数据竞争意味着您具有未定义的行为。具有未定义的行为意味着我们不再能够对该程序进行推理,并且您获得的任何输出都是“正确的”。

如果您珍惜自己的理智,则可以在检查之前降低性能并锁定互斥锁。也就是说,该列表甚至可能不是您的正确容器。如果您可以让我们确切知道您在做什么,我们也许可以建议一个更好的容器。

  • @NgọcKhánhNguyễn这是错误的。竞争条件是“可读写”或“可写”。如果您不相信我,请阅读[关于数据竞赛的标准部分](https://timsong-cpp.github.io/cppwp/intro.races) (6认同)
  • @NgọcKhánhNguyễn如果他们将元素添加到列表中,那么在您同时写入和读取大小时,无疑会导致数据争用。 (3认同)

Fur*_*ish 6

有一个读取和写入(最有可能的size成员std::list,如果我们假设它的命名一样,)不同步在reagard彼此。想象一个线程empty()(在您的外部if())调用,而另一个线程进入内部if()并执行pop_back()。然后,您正在读取可能正在修改的变量。这是未定义的行为。