gpt4 book ai didi

c++ - 互斥锁指针双重NULL检查的原因是什么

转载 作者:IT老高 更新时间:2023-10-28 22:26:02 25 4
gpt4 key购买 nike

我最近读了一本关于系统软件的书。里面有个例子看不懂。

volatile T* pInst = 0;
T* GetInstance()
{
if (pInst == NULL)
{
lock();
if (pInst == NULL)
pInst = new T;
unlock();
}
return pInst;
}

作者为什么要检查两次(pInst == NULL)

最佳答案

当两个线程第一次尝试同时调用 GetInstance() 时,在第一次检查时都会看到 pInst == NULL。一个线程将首先获得锁,这允许它修改pInst

第二个线程将等待锁可用。当第一个线程释放锁时,第二个会得到它,现在pInst的值已经被第一个线程修改了,所以第二个不需要创建一个新的实例。

只有 lock()unlock() 之间的第二次检查是安全的。它可以在没有第一次检查的情况下工作,但它会更慢,因为每次调用 GetInstance() 都会调用 lock()unlock() .第一次检查避免了不必要的 lock() 调用。

volatile T* pInst = 0;
T* GetInstance()
{
if (pInst == NULL) // unsafe check to avoid unnecessary and maybe slow lock()
{
lock(); // after this, only one thread can access pInst
if (pInst == NULL) // check again because other thread may have modified it between first check and returning from lock()
pInst = new T;
unlock();
}
return pInst;
}

另见 https://en.wikipedia.org/wiki/Double-checked_locking (复制自 interjay 的评论)。

注意:此实现要求对 volatile T* pInst 的读写访问都是原子的。否则,第二个线程可能会读取刚刚被第一个线程写入的部分写入值。对于现代处理器,访问指针值(而不是指向的数据)是原子操作,但不能保证适用于所有架构。

如果对 pInst 的访问不是原子的,第二个线程可能会在获取锁之前检查 pInst 时读取部分写入的非 NULL 值,然后执行 return pInst 在第一个线程完成其操作之前,这将导致返回错误的指针值。

关于c++ - 互斥锁指针双重NULL检查的原因是什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56441027/

25 4 0