我在Linux应用程序中使用Boost 1.41,它在一个线程上接收数据并将其粘贴到队列中,另一个线程将其从队列中弹出并处理它。为了使线程安全,我使用了范围锁。
我的问题是,很少有锁定功能在读取功能中失败,并显示消息:
void boost :: mutex :: lock()断言'!pthread_mutext_lock(& m)'失败
这种情况非常罕见,在最后一次运行中,失败前需要36小时(~4.25M交易)。下面列出了读写函数,它始终位于Assert出现的读取函数中
写入队列
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;
}
我用Google搜索并在销毁scoped_locks时发现了一些问题,但没有得到锁定。我还搜索了发布说明和Trac日志,看看是否已被其他人识别为问题。我认为我的代码就像它得到的一样简单,但显然有些东西已经出现了。有什么想法吗? TIA 保罗
答案 0 :(得分:0)
您的程序中存在一个线程安全问题,在这段代码中:
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()
和{{1} } 失败。除非你只有一个读者线程,否则你也需要进行大小检查。
我不知道这是否是断言失败的原因。断言意味着对pop()
的调用返回了一个非零值,表示错误。不幸的是,Boost没有显示possible pthread_mutex_lock
errors究竟发生了什么。