我知道这些书对于std :: deque的中度线程安全有什么看法,但我的经验证明不是这样。我正在使用VS 2010.至少有两个线程(可能是N个线程但添加线程只会使问题更快发生)每个线程运行相同的代码。每个线程包含相同的代码,但是指向包含deque的结构的唯一实例的指针被传递给每个线程,因此理论上它们每个都有自己的deque来使用。但是在不同的时间,当线程尝试访问deque(总是读取)时,我会收到错误。 deque定义如下:
struct A
{
deque<TAS*> dqTas;
}
TAS是指向另一个结构的指针。
结构A创建为
A* Aptr = new A;
TAS结构也以相同的方式创建
TAS* pTas = new TAS
错误的特点是:
1)它们在代码中随机发生。在发生错误之前,线程可能会运行几分钟处理读取/写入双端队列的数据。
2)更多线程会导致问题更快发生。 1个线程永远不会发生这个问题。
3)错误信息不同,说deque无法解除引用或索引超出范围。如果deque无法解除引用错误,则检查数据的原因完全无法检测到。一切都按顺序查看,指针,双端队列中的现有数据等。如果问题是索引超出范围,那么不知何故,一个或多个数据项(几百个)突然在deque本身中被破坏。
我已删除了每个工作流程路径中的所有删除操作,因此无意中删除了内存可能不是问题。
它似乎唯一可能导致这是std :: deque代码中的全局计数器或指针。这些错误的特征表示线程冲突源。我甚至验证过每个struct实例的地址都不同。理论上应该没有碰撞的可能性,因为每个线程都有自己的双端队列副本。这种设置发生这种情况的唯一方法是std :: deque代码中有一个全局ptr或计数器。
还有其他人有这种经历吗?在这种情况下,boost deque功能会表现得更好吗?
如果您想知道,这是gpfs:
的代码pTs->dqTas.push_front( pTb ); <<GPF happens after a write
#if defined (DEBUG)
long d2 = pTs->dqTas.size()-1;
if( d2 > 0 )
{
TASBAR* pDel2;
//pDel2 = pTs->dqTas[d2];
pDel2 = pTs->dqTas.at(d2); //<<GPF happens here
}
#endif
解决方案:
谢谢大家的意见。问题得到了解决,它与deque容器无关。随机的deque腐败是问题的症状。问题是由一些在线程实例化的类的函数中本地声明的旧静态变量引起的。这些变量被另一个线程中同一个deque中保存的其他对象的地址覆盖。我摆脱了那些,一切都按预期开始工作。虽然听起来很简单,但要记住的一点是,静态变量本质上是全局变量(即使在函数内本地定义),也是跨线程的。可能最好在任何进入可以运行相同代码的多个实例的线程的代码中完全避免它们,除非它非常清楚为什么以及它们如何被使用。
答案 0 :(得分:3)
通常没有容器是&#34;线程安全的&#34;。它只是一个容器。我建议你自己让它保持线程安全。使用堆栈上的std :: mutex创建std :: lock_guard对象将使您的代码线程安全。希望它有所帮助:在代码示例下面:
std::mutex lockMutex;
std::lock_guard<std::mutex> lock(lockMutex);