首先我的代码使我的解释更清楚:
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*
之后,我无法立即将其删除,因为它可能需要等待几个周期,因此可能仍在等待中。实现此目的的常用方法是什么?
答案 0 :(得分:5)
您可以立即将其删除。
引用C ++标准:
~ condition_variable();
要求:
*this
上不应阻塞任何线程。 [注意: 所有线程应已被通知;他们可能随后会封锁wait
中指定的锁。这放宽了通常的规则 要求所有wait
调用在销毁之前进行。 仅 解除封锁wait
的通知必须在销毁之前发生。
基本上需要wait
个函数才能自动执行锁定和等待:
notify_one
和notify_all
的执行是原子的。执行wait
,wait_for
和wait_until
中的一个必须在三个原子部分中执行:
- 释放互斥锁并进入等待状态; </ li>
wait
的解锁;和- 重新获得锁。
notify
一旦唤醒线程,就应将其视为“未阻塞”并应对互斥体进行竞争。
关于std::mutex
有类似的保证:互斥对象销毁之前,线程不需要离开unlock
。
引用C ++标准:
实现应提供
lock
和unlock
操作,如 如下面所描述的。为了确定数据的存在 种族,这些行为就像原子操作。lock
和unlock
单个互斥锁上的操作应看起来是总共发生的 订单。
稍后:
注意:线程A调用
unlock()
,释放互斥锁后,它是 另一个线程B可能锁定相同的互斥锁,请注意 不再使用,请在线程A之前对其进行解锁并销毁它 似乎是从其unlock
通话中退回的。。
在使用对象内部的互斥锁来保护对象引用计数器时,需要采取某些保证措施来避免类似this之类的问题。
请注意,这不能保证您的实现在这方面没有错误。过去,glibc有多个与破坏同步对象有关的错误,特别是pthread_mutex_unlock
是accessing mutex before returning。
答案 1 :(得分:0)
一个简单的解决方法:将delete foo
之后的foo->cv.wait(...);
移入线程1。
一个更好的解决方法是更改设计以使其适用于std::shared_ptr
,而无需手动delete
调用。