如何在多线程中同步 "for" 循环计数器?
How to sync "for" loop counter in multithread?
如何在多线程上同步 "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
我可以吗?
如果您使用 OpenMP 对循环进行线程化,则可以使用 #pragma omp barrier
语句。
在 C++11 中,您可以使用 condition_variable 阻塞所有线程,直到它们到达同一位置。
一种方法是为线程使用一些变量来协调事物(为了简单起见,在下文中它们是全局变量)。
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();
}
您可以使用 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" 循环计数器?
如果这些多线程程序
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
我可以吗?
如果您使用 OpenMP 对循环进行线程化,则可以使用 #pragma omp barrier
语句。
在 C++11 中,您可以使用 condition_variable 阻塞所有线程,直到它们到达同一位置。
一种方法是为线程使用一些变量来协调事物(为了简单起见,在下文中它们是全局变量)。
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();
}
您可以使用 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
不是线程安全的。