如何在多线程中同步“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(循环屏障)解析和用例

同步类

你如何使用WaitGroup确保goroutine在for循环中完成?

javascript中for循环的计数器

synchronized重入后抛出异常,锁释放了吗

如何在 Java 中的 Iterable 的 for 循环中创建一个计数器并获取计数器变量的值