假设我们有一个访问一些全局共享数据的函数 - 并且假设这个函数将被多个并发线程调用。
自然地,我们需要以某种方式同步对这些数据的访问。是否有可能通过我们有一个原子标志的机制来做到这一点,然后无论哪个线程设法设置标志都可以继续访问共享数据?而丢失的线程不会阻塞在锁上,而只是从函数中返回。
类似下面的内容:
给定一些全局共享的数据以及一个同步标志:
namespace global {
int x;
int y;
std::atomic_flag sync_flag = ATOMIC_FLAG_INIT;
}
我们的函数将被并发线程访问:
void race()
{
// See if we won the race
//
if (!global::sync_flag.test_and_set())
{
// We won
//
global::x = 10;
global::y = 11;
}
else
{
// We lost...
return;
}
}
上述代码是否保证global::x
和global::y
将仅由单个线程安全访问,并且不会出现竞争条件?还是由于内存排序问题,这不能得到保证?
请注意,我们实际上从未锁定互斥量或任何东西,因此没有线程最终阻塞。这里的想法只是为了确保只有一个线程被允许在这里访问(非原子)全局变量。
当然,在获胜线程完成后,如果我们打算再次调用 race()
,我们需要以某种方式安全地清除原子标志。这是一个我还没有想太多的问题,但它确实超出了这个问题的范围。
那么上面的代码是否没有竞争条件(对于 race()
的单个调用)?
最佳答案
是的。只有一个线程可以在标志上获得尚未设置的测试。这比互斥锁有一个优势,因为在某些体系结构上,原子标志可以通过无锁操作完成。
关于c++ - 使用 "got there first"标志而不是锁/互斥来同步对数据的访问,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30948958/