避免在增加计数器时出现争用条件
Avoid race condition when incrementing a counter
我以前发过关于这个话题的文章,但到目前为止我还没有太多的运气。我把它归结为我的一个糟糕的问题。这次我做了一个简短的可编译示例,显示了我试图避免的不良行为。我希望这得到赞赏。
问题是两个(或多个)线程被设置为运行相同的进程,它们的"id"决定了它们对变量数据的哪一部分进行操作。目前,两个线程都将更新计数器。
电流输出如下所示,
tid = 0, var[tid] = 0
tid = 0, var[tid] = 1
tid = 0, var[tid] = 2
tid = 0, var[tid] = 3
tid = 0, var[tid] = 4
tid = 0, var[tid] = 5
tid = 0, var[tid] = 6
tid = 0, var[tid] = 7
tid = 0, var[tid] = 8
tid = 0, var[tid] = 9
tid = 1, var[tid] = 0
Press any key to continue . . .
所需的输出应该是这样的...
tid = 0, var[tid] = 0
tid = 1, var[tid] = 0
tid = 0, var[tid] = 1
tid = 1, var[tid] = 1
tid = 0, var[tid] = 2
tid = 1, var[tid] = 2
tid = 0, var[tid] = 3
tid = 1, var[tid] = 3 etc.
此处的任何指导将不胜感激。
编辑:我用按预期工作的代码更新了答案。
[注意效率在这里很重要,我想尽快完成这个过程]
#include <iostream>
#include <boost/thread.hpp>
int var[2];
int mT;
int mTotalSamples;
boost::mutex mCountMutex;
boost::thread *threadMap[2];
using namespace std;
void process()
{
int tid = 1;
// sleep for 1 seconds - just to make sure threadMap
// has been assigned (only ncessary for this demo).
boost::this_thread::sleep(boost::posix_time::seconds(1));
if (threadMap[0]->get_id() == boost::this_thread::get_id()){ tid = 0;}
while ( mT < mTotalSamples )
{
// perform processing
var[tid] = mT;
// processing complete
mCountMutex.lock(); // (a thread waits to aquire mutex)
cout << "tid = " << tid << ", var[tid] = " << var[tid] << endl;
mT++; // How to stop both threads incrementing this?
mCountMutex.unlock();
}
}
int main()
{
boost::thread_group threads;
mT = 0;
mTotalSamples = 10;
threadMap[0] = threads.create_thread( boost::bind(&process) );
threadMap[1] = threads.create_thread( boost::bind(&process) );
threads.join_all();
return 0;
}
从预期的输出来看,您希望线程在每次更新后同步。boost
库提供了 boost::barrier,如果你在 process
中 while-循环的开头或结尾为它放一个wait
,应该可以解决问题。
#include <iostream>
#include <boost/thread.hpp>
int var[2];
int mT;
int mTotalSamples;
boost::mutex mCountMutex;
boost::thread *threadMap[2];
boost::barrier bar(2);
using namespace std;
void process()
{
int tid = 1;
// sleep for 2 seconds - just to make sure threadMap
// has been assigned (only ncessary for this demo).
boost::this_thread::sleep(boost::posix_time::seconds(2));
if (threadMap[0]->get_id() == boost::this_thread::get_id()){ tid = 0;}
while ( mT < mTotalSamples )
{
// perform processing
var[tid] = mT;
// processing complete
bar.wait();
if (threadMap[0]->get_id() == boost::this_thread::get_id())
{
mT++;
cout << "var[0] = " << var[0] << endl;
cout << "var[1] = " << var[1] << endl;
}
bar.wait();
}
}
int main()
{
boost::thread_group threads;
mT = 0;
mTotalSamples = 10;
threadMap[0] = threads.create_thread( boost::bind(&process) );
threadMap[1] = threads.create_thread( boost::bind(&process) );
threads.join_all();
return 0;
}
在 process() 中将此int mT;
设为本地 - 而不是全局。或者你需要一个int mT[2];
那么你就不需要互斥锁了。
相关文章:
- 并行块(线程清理器)之外的 OpenMP 中的争用条件;误报?
- 如何在C++中创建争用条件
- C++上的手动重置事件(来自 C#)实现:如何避免争用条件
- 作为随机数生成器的争用条件
- 智能指针析构函数争用条件
- 尽管互斥锁,线程中的争用条件
- 在C++中递增和递减全局变量时的争用条件
- 为什么此代码不创建争用条件?
- __has_include() 和后续 #include 之间是否存在争用条件
- 什么保证两个不相关的线程中的不同不相关对象没有(不可避免的)争用条件?
- 此工厂方法是否会导致争用条件?
- 争用条件 2 个线程交替
- 标准::condition_variable 中可能存在的争用条件
- 启动子进程时的争用条件导致从管道读取挂起
- 当只有一个线程写入 c++ 中的布尔变量时,是否存在争用条件
- 避免在增加计数器时出现争用条件
- 是否有 std 或提升容器可以避免其插入和查找方法之间的争用条件
- 增强进程间争用条件预防
- pthread_once() 中的争用条件
- 发布标准实现争用条件