【发布时间】:2015-07-26 06:52:13
【问题描述】:
在使用多线程时,我经常遇到以下问题:
我有一个对象,比如说网络接收器(但可以是任何东西)。还有一个获取数据的函数。现在有时根本没有数据,你想让线程等待获取它的数据。一个阻塞调用,非常类似于 Berkeley 套接字及其派生实现。
原理很简单:
现在当然还有其他方法可以实现这一点。但我通常使用 C++11 的实现如下:
-
Object A在专用于此任务的单独线程上调用对象 B 中的函数。 -
Object B使用std::condition_variable构造来阻塞线程,直到实际获取数据。 -
Object A将数据放入队列,由主线程读取。
现在我的实际问题出现在object B 的销毁上,如果它必须在object A 之前被销毁(返回一个nullptr,或者在阻塞调用中类似的东西)。我真的不知道如何有效地结束object B。
主要问题是object B不知道线程,一个线程只能有一个句柄,在object A里面。
示例:
一些代码来说明我的问题。
假设我在对象 B 中有这个函数:
data* getData
{
std::unique_lock<std::mutex>l_newDataWaiterLock(m_newDataWaiterMutex);
m_newDataWaiter.wait(l_newDataMutex);
if(!running)
return nullptr
else
return data;
}
还有这个析构函数:
~ObjectB()
{
m_running = false;
m_newDataWaiter.notifyAll();
//Point X
}
使用这些成员变量:
std::condition_variable m_newDataWaiter;
std::atomic<bool> m_running;
我们仍然存在析构函数必须在指定的Point X 处等待的问题,直到所有其他线程都收到通知并返回 null。
现在我可以使用原子计数器、更多 std::condition_variables 和互斥体来制作一些东西。但我觉得必须有一个更优雅、更可靠的解决方案来解决这个问题:)。由于此解决方案需要在 object B 的整个生命周期的每个 getData 调用中发出通知。
注意:我使用的是 C++11,所以我用它来说明一切。我希望用它来解决它。虽然这当然是一个更普遍的并发问题。
【问题讨论】:
标签: c++ multithreading c++11 destructor blocking