我在一个类中有以下两个成员函数。 _mtxWrite是一个互斥对象,用于使写函数线程安全。在重负载期间,有时writeHandler不会被调用。然后_mtxWrite不会被释放,从而导致死锁。检测情况和解决死锁的最佳方法是什么?
template <class TSession>
void write(boost::shared_ptr<TSession> pSession,
boost::shared_ptr<CInProtocolBase> pMessage)
{
std::vector<unsigned char>* pData = new std::vector<unsigned char>;
pMessage->serialize(*pData);
_mtxWrite.lock();
boost::asio::async_write(_socket,boost::asio::buffer(&pData->at(0),
pData->size()),
boost::bind(&this_type::writeHandler<TSession>,
shared_from_this(),pSession,pData,boost::asio::placeholders::error));
}
template <class TSession>
void writeHandler(boost::shared_ptr<TSession> pSession,
std::vector<unsigned char>* pData,const boost::system::error_code& ec)
{
delete pData;
_mtxWrite.unlock();
if(ec)
{
_socket.get_io_service().post(boost::bind(&TSession::errorHandler,
pSession,ec));
}
}
答案 0 :(得分:2)
您的代码锁定了调用async_write()
的互斥锁,并在处理程序中解锁它。如果这些操作发生在不同的线程中,那么这将违反unlock()
preconditions(当前线程拥有互斥锁)。这可能会导致您的僵局。通常,分离的锁定和解锁通常表示设计欠佳。
处理异步写入的更好方法是使用队列。逻辑看起来像:
写功能:
async_write
。scoped_lock
超出范围)。写处理程序:
async_write
。scoped_lock
超出范围)。使用这种方法,锁定是本地化的,没有机会发生死锁。 @ TannerSansbury在评论中使用链进行同步而不是互斥的指针将起到类似的作用 - 它隐含地为链中运行的任何函数提供排除。
我从未遇到过一个没有被调用的写入处理程序,最终没有被确定为我自己的错误,但是你可以通过设置计时器时使用boost::asio::deadline_timer来监视它async_write()
并在写处理程序中取消它。