【问题标题】:How to sync "for" loop counter in multithread?如何在多线程中同步“for”循环计数器?
【发布时间】: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)。你希望计数器如何同步?您是否要始终保证按顺序打印日志消息?如果是这样,你为什么想要多个线程?
  • 这是提问的简化程序。我的原始程序是模拟多代理系统(分布式随机算法)。在原始程序中,我想同步所有代理的试验次数。

标签: c++ multithreading mutex sync critical-section


【解决方案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 不是线程安全的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-08-20
        • 2011-06-24
        • 2022-01-23
        • 1970-01-01
        • 2013-11-07
        • 2023-03-03
        相关资源
        最近更新 更多