如何在特定的代码行同步两个 CPU 线程?
Posted
技术标签:
【中文标题】如何在特定的代码行同步两个 CPU 线程?【英文标题】:How can I synchronize two CPU threads at a specific line of code? 【发布时间】:2022-01-07 05:45:35 【问题描述】:我有两个线程和一个 CPU。
我希望在其程序中较早到达 A 行的两个线程中的每一个都等待另一个线程到达 A 行,之后两个线程继续运行它们的程序。我已经这样做了,但是我希望 A 行的两个线程同时运行它们的程序。
我怎样才能做到这一点?
我的代码:
//headers
static volatile bool waitFlag[2];
void *threadZero(void*)
//some codes
waitFlag[1] = true;
while(!waitFlag[0]);
//line A of thread zero
//some codes
void *threadOne(void*)
// some codes
waitFlag[0] = true;
while(!waitFlag[1]);
//line A of thread one
//some codes
int main()
waitFlag[0] = waitFlag[1] = false;
//Creates two threads and waits for them to finish.
【问题讨论】:
所以请注意,仅使用普通的bool
不是线程安全的,并且会导致数据竞争,从而导致未定义的行为。在 C 中,您应该使用 OS 原语或 C11 atomics(通常受支持)
Re "OS 原语",这是指互斥体、信号量等。如果涉及到非平凡的等待,这些比使用忙等待循环更合适原子。
@mehran 因为bool
不是线程安全的,CPU 可能看不到跨线程的更新。 C 标准明确规定,为了不引起数据竞争,它要么需要在屏障(OS Primitive)后面,要么在从多个线程访问时使用原子。
***.com/questions/26231727/…
如果您愿意切换到 C++20,std::latch
将这一切都包装在一个不错的包中。请注意,它仍然不能确保两个线程实际上同时运行;这总是受操作系统调度程序的支配。
【参考方案1】:
繁忙的循环对此目的是低效的。你想要的是一个condition、一个mutex和一个简单的计数器:
-
锁定互斥体。
增加计数器。
如果计数器是
2
,则按条件广播。
否则等待条件。
解锁互斥锁。
通过更改计数器的阈值,这个逻辑可以很容易地适应任意数量的线程。最后一个增加计数器的线程(受互斥锁保护)将在条件下广播,并将同时解锁自己和所有其他线程。如果要多次同步,也可以重置计数器。
这是一个例子:
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/random.h>
pthread_cond_t cond;
pthread_mutex_t cond_mutex;
unsigned int waiting;
// Sleep a random amount between 0 and 3s.
// This is just for testing, you don't actually neeed it.
void waste_time(void)
unsigned us;
getrandom(&us, sizeof(us), 0);
us %= 3000000;
fprintf(stderr, "[%lx] Sleeping %u us...\n", pthread_self(), us);
usleep(us);
void synchronize(void)
pthread_mutex_lock(&cond_mutex);
if (++waiting == 2)
pthread_cond_broadcast(&cond);
else
while (waiting != 2)
pthread_cond_wait(&cond, &cond_mutex);
pthread_mutex_unlock(&cond_mutex);
void *threadZero(void *_)
waste_time();
// ...
synchronize();
fprintf(stderr, "[%lx] Resuming.\n", pthread_self());
// ...
return NULL;
void *threadOne(void *_)
waste_time();
// ...
synchronize();
fprintf(stderr, "[%lx] Resuming.\n", pthread_self());
// ...
return NULL;
int main(void)
pthread_t zero, one;
pthread_create(&zero, NULL, threadZero, NULL);
pthread_create(&one, NULL, threadOne, NULL);
// ...
pthread_join(zero, NULL);
pthread_join(one, NULL);
return 0;
【讨论】:
@ikegami 啊,对!感谢您的编辑。 注意:虽然 C11 did introduce primitives for this 尚未跨平台,但截至 2021 年目前支持有限。以上是关于如何在特定的代码行同步两个 CPU 线程?的主要内容,如果未能解决你的问题,请参考以下文章