如何在多线程中同步“for”循环计数器?
Posted
技术标签:
【中文标题】如何在多线程中同步“for”循环计数器?【英文标题】:How to sync "for" loop counter in multithread? 【发布时间】:2015-06-26 17:08:31 【问题描述】:如何在多线程上同步“for”循环计数器?
如果这些多线程程序
void Func(int n)
for(int i=0; i<n; i++) //at the same time with other Func()
cout << i <<endl;
void main()
std::thread t1(Func(2));
std::thread t2(Func(2));
t1.join();
t2.join();
在并行执行 Func() 时,我想同步“for”循环计数器“i”。
例如,程序有可能输出结果
0
1
0
1
但我想总是得到结果
0
0
1
1
可以吗?
【问题讨论】:
您的程序也可以打印其他内容(例如00
)。你希望计数器如何同步?您是否要始终保证按顺序打印日志消息?如果是这样,你为什么想要多个线程?
这是提问的简化程序。我的原始程序是模拟多代理系统(分布式随机算法)。在原始程序中,我想同步所有代理的试验次数。
【参考方案1】:
如果您使用 OpenMP 线程化您的循环,您可以使用 #pragma omp barrier
语句。
在 C++11 中,您可以使用 condition_variable 阻塞所有线程,直到它们到达同一位置。
【讨论】:
【参考方案2】:一种方法是使用一些变量让线程协调事物(在下文中它们是全局变量,只是为了简单起见)。
mutex m;
condition_variable c;
static int index = 0;
static int count = 2;
index
变量表示线程在哪个索引处,count
变量表示索引处仍有多少线程。
现在你的循环变成了:
void Func(int n)
for(int i=0; i<n; i++) //at the same time with other Func()
unique_lock<mutex> l(m);
c.wait(l, [i]()return index == i;);
cout << i <<endl;
if(--count == 0)
++index;
count = 2;
c.notify_one();
这里是完整的代码:
#include <thread>
#include <mutex>
#include <condition_variable>
#include <iostream>
using namespace std;
mutex m;
condition_variable c;
static int index = 0;
static int count = 2;
void Func(int n)
for(int i=0; i<n; i++) //at the same time with other Func()
unique_lock<mutex> l(m);
c.wait(l, [i]()return index == i;);
cout << i <<endl;
if(--count == 0)
++index;
count = 2;
c.notify_one();
int main()
std::thread t1(Func, 20);
std::thread t2(Func, 20);
t1.join();
t2.join();
【讨论】:
【参考方案3】:您可以使用std:atomic
变量并将其传递给所有线程。
void Func(int n, int & i)
for (; i<n; i++) //at the same time with other Func()
cout << i << endl;
void main()
std::atomic<int> counter = 0;
std::thread t1(Func, 2, std::ref(counter));
std::thread t2(Func, 2, std::ref(counter));
t1.join();
t2.join();
您还应该注意,您在示例中创建线程的方式是不正确的。其次,如果您在多个线程中使用cout
,则每个cout
都应使用std::mutex
进行保护,因为cout
不是线程安全的。
【讨论】:
以上是关于如何在多线程中同步“for”循环计数器?的主要内容,如果未能解决你的问题,请参考以下文章
AQS同步组件-CyclicBarrier(循环屏障)解析和用例