等待期间破坏condition_variable

时间:2018-09-12 15:34:36

标签: c++ multithreading c++11

首先我的代码使我的解释更清楚:

struct Foo {
    std::condition_variable cv;
};
static Foo* foo; // dynamically created object

// Thread1
foo->cv.wait(...);


// Thread2
foo->cv.notify();
delete foo; // thread1 might have not left the wait function yet

我正在尝试删除std::condition_variable中的wait。因此,根据我的理解,我必须先通知它,使其离开等待例程的位置,然后再将其删除。但是在调用notify*之后,我无法立即将其删除,因为它可能需要等待几个周期,因此可能仍在等待中。实现此目的的常用方法是什么?

2 个答案:

答案 0 :(得分:5)

您可以立即将其删除。

引用C ++标准:

  

~ condition_variable();

     

要求*this上不应阻塞任何线程。 [注意:   所有线程应已被通知;他们可能随后会封锁   wait中指定的锁。这放宽了通常的规则   要求所有wait调用在销毁之前进行。 仅   解除封锁wait的通知必须在销毁之前发生。

基本上需要wait个函数才能自动执行锁定和等待:

  

notify_onenotify_all的执行是原子的。执行   waitwait_forwait_until中的一个必须在三个原子部分中执行:

     
      
  1. 释放互斥锁并进入等待状态; <​​/ li>   
  2. wait的解锁;和
  3.   
  4. 重新获得锁。
  5.   

notify一旦唤醒线程,就应将其视为“未阻塞”并应对互斥体进行竞争。


关于std::mutex有类似的保证:互斥对象销毁之前,线程不需要离开unlock

引用C ++标准:

  

实现应提供lockunlock操作,如   如下面所描述的。为了确定数据的存在   种族,这些行为就像原子操作。 lockunlock   单个互斥锁上的操作应看起来是总共发生的   订单。

稍后:

  

注意:线程A调用unlock(),释放互斥锁后,它是   另一个线程B可能锁定相同的互斥锁,请注意   不再使用,请在线程A之前对其进行解锁并销毁它   似乎是从其unlock通话中退回的。

在使用对象内部的互斥锁来保护对象引用计数器时,需要采取某些保证措施来避免类似this之类的问题。


请注意,这不能保证您的实现在这方面没有错误。过去,glibc有多个与破坏同步对象有关的错误,特别是pthread_mutex_unlockaccessing mutex before returning

答案 1 :(得分:0)

一个简单的解决方法:将delete foo之后的foo->cv.wait(...);移入线程1。

一个更好的解决方法是更改​​设计以使其适用于std::shared_ptr,而无需手动delete调用。