4

我试图了解锁是如何工作的。

假设我想在 C++ 中实现一个非常简单的锁

class Resource{
    public:
    bool lock();
    void unlock();
    ... methods to change/read the Resource ...

    private:
    bool isLocked;
}

资源的用户调用lock(),如果isLocked为真,则lock()返回假,资源的用户要么等待,要么做其他事情。如果isLocked为假,则lock()设置isLocked为真,并返回真。然后调用者可以对资源做任何他想做的事情。之后他调用unlock()资源设置isLocked为假。

但是,如果资源的两个用户lock()恰好同时调用呢?这种情况很少发生吗?我认为更正式地说,这涉及使lock()操作“原子”,尽管我不确定该词的含义。

4

3 回答 3

5

使用旧的标准 C++,您无法实现自己的锁,因为锁变量本身处于数据竞争中。

C++11 和 C11 添加了原子变量,您可以将其用于此目的;例如在 C++ 中:

#include <atomic>

std::atomic<bool> isLocked;

bool lock() { return !isLocked.exchange(true); }

void unlock() { isLocked = false; }

这里的关键是原子交换和(隐式)原子存储,它们生成特殊的硬件指令并且始终没有竞争,并且您不能用普通变量“伪造”它们。

于 2012-04-07T22:15:07.453 回答
3

“原子”意味着操作不能被中断。也就是说,无论其他线程/进程的行为如何,您都可以确定该操作的语义是相同的。您是对的,您的lock()通话中的某些内容可能必须是原子的。大多数架构都提供了一些有用的指令,并保证了原子行为——您可能还会发现一些构建在这些操作上的库,以便在您正在编程的更高层为您提供更大的灵活性。

于 2012-04-07T22:06:18.970 回答
1

这并不罕见。它被称为竞争条件,是多线程代码中许多(如果不是大多数)错误的原因。

C++ 标准实际上并没有任何线程/原子性等概念,1因此您需要依赖操作系统提供的同步原语(或者可能通过 Boost)。


1. 这不再适用于 C++11。

于 2012-04-07T22:06:39.750 回答