3

如果我有一个临界区,我必须实现一个锁定它的方法。我看到了以下变体:

while(lock)
{
    //do nothing
}
lock = true;
// code of critical section
lock = false;

但是,我对此持怀疑态度,因为理论上,多个线程可以执行while(lock)(检查并查看它是否为假),并一起进入关键部分,因为while(lock)并且lock = true;不是在一个连续的块中执行。我错了吗?或者这确实是一种不安全的方法?

4

3 回答 3

5

你是对的——这不安全。不多说了。

编辑:不,关于这个结构,真的,真的没什么好说的了。这不是自旋锁,也不是很像自旋锁。对于自旋锁,你需要一些类似这样的东西:

// note: incomplete, not reentrant, not intended for real use
atomic_type spin_lock = 0;

// enter the spin lock:
int prev_value;

while ((prev_value = test_and_set(&spin_lock, 1)) != 0 || spin_lock != 1)
    ;
// code of critical section

// release the spin lock:
test_and_set(&spin_lock, 0);

这里重要的一点是,要进入自旋锁,需要先获取之前的值,然后原子地设置新的值。然后您必须验证对锁的写入是否将其从“非拥有”状态更改为“拥有”状态。

于 2012-05-21T17:51:14.693 回答
3

这是“几乎安全的”,即根本不安全。它所缺少的正是您所看到的 - 多个线程可以看到lock == false并进入临界区。它需要一个原子操作,它必须得到硬件的支持——一种保证只有一个执行线程可以获得锁的方法。

也就是说,如果您正在编写的系统可以在互斥故障中幸存下来,并且可以正常处理偶尔的故障(可能是日志记录或偶尔损坏的条目不一定会导致完全故障的东西),那么这种模式可能“有点”工作...

于 2012-05-21T17:56:59.207 回答
0

您尝试实现的称为自旋锁。新的 C 标准 C11 实现了一个原始数据类型,称为atomic_flag可以像这样使用。几乎所有现代硬件都支持它,但不幸的是,大多数编译器还没有完全支持它的语法级别,但有自己的扩展。例如 gcc 有内置函数__sync_lock_test_and_set__sync_lock_release为此。

于 2012-05-21T18:22:08.607 回答