我正在努力了解锁是如何工作的。
假设我想在C ++中实现一个非常简单的锁定
class Resource{
public:
bool lock();
void unlock();
... methods to change/read the Resource ...
private:
bool isLocked;
}
资源的用户调用lock()
,如果isLocked
为真,则lock()
返回false,资源的用户必须等待或执行其他操作。如果isLocked
为false,则lock()
将isLocked
设置为true,并返回true。然后调用者可以对资源做任何他想做的事情。之后他在资源上调用unlock()
将isLocked
设置为false。
但是,如果资源的两个用户在同一时间调用lock()
怎么办?这种情况很少发生吗?我认为更正式地说,这涉及使lock()
操作“原子化”,尽管我并不确定这个词是什么意思。
答案 0 :(得分:5)
使用旧的标准C ++,您无法实现自己的锁,因为锁变量本身处于数据竞争中。
C ++ 11和C11添加原子变量,您可以将其用于此目的;例如在C ++中:
#include <atomic>
std::atomic<bool> isLocked;
bool lock() { return !isLocked.exchange(true); }
void unlock() { isLocked = false; }
这里的关键是原子交换和(隐式)原子存储,它生成特殊的硬件指令,并且总是无竞争,并且你不能用普通变量“伪造”。
答案 1 :(得分:3)
“原子”表示操作无法中断。也就是说,无论其他线程/进程的行为如何,您都可以确定该操作的语义是相同的。你的lock()
电话中的某些内容可能必须是原子的,这是对的。大多数体系结构提供了一些有保证的原子行为的有用指令 - 您可能还会发现一些基于这些操作的库,以便在您编程的更高层提供更大的灵活性。
答案 2 :(得分:1)
这一点都不罕见。它被称为竞争条件,并且是多线程代码中许多(如果不是大多数)错误的原因。
C ++标准实际上没有线程/原子性的任何概念,等等, 1 所以你需要依赖你的操作系统提供的同步原语(或者可能通过Boost)。
<小时/> <子> 1。对于C ++ 11,情况不再如此。