是 go valid 中的双重检查锁定实现

问题描述 投票:0回答:1

这是另一个

don't be smart
GO问题。当然有
once
原语可以使用,但这纯粹是为了讨论目的。

type impl struct {
    fLock         *sync.Mutex
    fValue        TValue
    fGetValueFunc XXXX
}
    var err basic.Error = nil
    lock := impl.fLock

    if lock != nil { // RACE
        lock.Lock()
        defer lock.Unlock()

        if impl.fLock != nil {
            impl.fValue, err = impl.fGetValueFunc()

            if err == nil {
                impl.fGetValueFunc = nil
                impl.fLock = nil // RACE CHECK Complains
            }
        }
    }

竞赛检查抱怨并发访问。但我假设这只是一个地址,并且已经保证对机器字的访问保证是原子的。

尽管竞赛检查抱怨,这种双重检查锁定仍然有效吗?

go concurrency
1个回答
0
投票

竞争检测器正在做什么:

通过竞争检测器,编译器使用记录访问内存的时间和方式的代码来检测所有内存访问,而运行时库则监视对共享变量的不同步访问。

因此,竞争检测器正在寻找对不受某些同步保护的共享变量(即互斥体、通道等)的访问。


    lock := impl.fLock // create a new var with the same pointer value

    if lock != nil { // READ the value of that pointer (outside synchronization)
        lock.Lock()
        defer lock.Unlock()

                // trimmed
                impl.fLock = nil // Write the value of that pointer (inside synchronization)

竞争检测器不知道代码的含义。但您可以合理地假设所有种族警告都应该得到修复(您不想养成忽略它们的习惯)。

在没有看到更广泛的代码上下文的情况下,很难确定程序的行为是什么。例如;

lock
有没有改变,并发在哪里等等

我们从您的例子中了解到:

我们所知道的是:

  • lock
    impl.fLock
    开始时是指向某个内存地址的同一个互斥体的两个指针,例如:
    0xc0000ac040
  • 假设
    lock
    从未被重新分配,则互斥量被锁定在
    lock.Lock()
  • impl.fLock = nil
    不会更改互斥锁,它只是将指针从
    0xc0000ac040
    更改为
    0x0
    (nil),
    lock
    的值将保持为
    0xc0000ac040

我们不知道

impl.fLock
被分配到哪里(或者更糟糕的是,重新分配)

  • 如果重新分配
    impl.fLock
    ,那么我们可能有两个独立的互斥体,一个位于原始地址
    0xc0000ac040
    ,另一个位于某个新地址;
    0xc000104040
  • 如果我们有两个互斥锁,那么
    lock.Lock()
    不再保护以下块:
        if impl.fLock != nil {
            // it's possible that some concurrent impl.fGetValueFunc = nil
            // gets scheduled between the nil check and the below line, so
            // impl.fGetValueFunc would panic
            impl.fValue, err = impl.fGetValueFunc()

            if err == nil {
                impl.fGetValueFunc = nil
© www.soinside.com 2019 - 2024. All rights reserved.