我在一个 linux 应用程序中使用 Boost 1.41,该应用程序在一个线程上接收数据并将其放入队列中,另一个线程将其从队列中弹出并进行处理。为了使其线程安全,我使用了作用域锁。
我的问题是,很少有锁定功能在读取功能中失败并显示以下消息:
void boost::mutex::lock() 断言 '!pthread_mutext_lock(&m)' 失败
这种情况非常罕见,在上次运行时,它花了 36 小时(约 4.25 亿个事务)才失败。下面列出读写函数,Assert总是在read函数中产生
写入队列
void PacketForwarder::Enqueue(const byte_string& newPacket, long sequenceId)
{
try
{
boost::mutex::scoped_lock theScopedLock(pktQueueLock);
queueItem itm(newPacket,sequenceId);
packetQueue.push(itm);
if (IsConnecting() && packetQueue.size() > MaximumQueueSize)
{
// Reached maximum queue size while client unavailable; popping.
packetQueue.pop();
}
}
catch(...)
{
std::cout << name << " Exception was caught:" << std::endl;
}
}
从队列中读取
while ( shouldRun )
{
try
{
if (clientSetsHaveChanged)
{
tryConnect();
}
size_t size = packetQueue.size();
if (size > 0)
{
byte_string packet;
boost::mutex::scoped_lock theQLock(pktQueueLock);
queueItem itm = packetQueue.front();
packet = itm.data;
packetQueue.pop();
BytesSent += packet.size();
trySend(packet);
}
else
{
boost::this_thread::sleep(boost::posix_time::milliseconds(50));
}
}
catch (...)
{
cout << name << " Other exception in send packet" << endl;
}
我用谷歌搜索并在销毁 scoped_locks 时发现了一些问题,但没有关于未能获得锁的问题。我还通过 boost 发行说明和 Trac 日志进行了搜索,以查看其他人是否已将其确定为问题。我认为我的代码已经很简单了,但显然有问题。有什么想法吗? TIA 保罗
最佳答案
您的程序中有一个线程安全问题,在这段代码中:
size_t size = packetQueue.size();
if (size > 0)
{
byte_string packet;
boost::mutex::scoped_lock theQLock(pktQueueLock);
queueItem itm = packetQueue.front();
packet = itm.data;
packetQueue.pop();
// ...
}
这里的问题是,在您检查队列大小和获得锁之间,其他一些读取线程可能会从队列中取出最后一项,这将导致 front()
和 pop()
失败。除非您只有一个读者线程,否则您也需要锁定大小检查。
不过我不知道这是否是断言失败的原因。该断言意味着对 pthread_mutex_lock
的调用返回了一个非零值,表示错误。不幸的是,Boost 没有准确显示 possible pthread_mutex_lock
errors 中的哪一个。已经发生了。
关于c++ - Boost 作用域锁定断言失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26262438/