围绕值变为空值的双重检查锁定?

编程入门 行业动态 更新时间:2024-10-27 06:19:12
本文介绍了围绕值变为空值的双重检查锁定?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

限时送ChatGPT账号..

这个线程是否安全:

class X;

class Once {
 public:
  Once(X* x) : x_(x) {}

  X* Get() {
    if (!x_) return NULL;
    // all dirty reads end up here.

    // This could be any type of scoped lock...
    some_scoped_lock lock(m);

    // if (!x_) return x_;  // omitted because it's a no op

    X* ret(x_);  // might get NULL if we waited for lock
    x_ = NULL;   // idempotent

    return ret;
  }

 private:
  X *x_;
  some_kind_of_mutex m;

  // Boilerplate to make all other constructors and default function private
  ....
}

(我对 c++11 和旧版本都感兴趣)

据我所知,双重检查锁定的问题是在某些内存中对受保护的 var 的写入建模可能会发生并尽早可见.我认为上面的代码没有这个问题,因为新值的有效性没有先决条件.我认为这是正确代码的唯一要求是锁下的所有读取必须相对于构造函数中的写入和锁下的写入来说是干净的.

As I understand it the problem with Double-checked locking is that in some memory models the write to the guarded var can occur and become visible to early. I think the above code doesn't have this issue because there is no precondition for the validity of the new value. I think the only requirement for this to be correct code is that all reads under the lock must be clean with respect to writes in the constructor and writes under the lock.

更新:好的,这似乎引发了未定义行为"陷阱,因此可以合法地做任何事情,包括耗尽您的银行账户.也就是说,是否存在任何行为不端的情况?

Update: OK, it seems that this invokes the "undefined behavior" pitfall and therefor can legally do anything, including drain your bank account. That said, are there any cases where it will misbehave?

推荐答案

根据 C++11 标准,行为未定义,因为存在数据竞争.更详细地说:线程 A 在行 x_ = NULL 中写入 x_ 并且线程 B 在带有 if 的行中从 x_ 读取(!x_) 返回 NULL.这两个操作没有先后顺序.这意味着存在数据竞争,这意味着未定义的行为.

According to the C++11 standard, the behavior is undefined, because there is a data race. In more detail: Thread A writes to x_ in the line x_ = NULL and Thread B reads from x_ in the line with if (!x_) return NULL. These two operations are not sequenced. That means there is a data race, and that implies undefined behavior.

您应该使用原子类型来避免数据竞争.这在您的示例中非常简单.但是,我认为这个问题更笼统.尽管如此:

You should use an atomic type to avoid the data race. This is very simple in your example. However, I think the question was more general. Nevertheless:

struct Once
{
    std::atomic<X*> _x;
    explicit Once(X* x) : _x{x} {}
    X* Get()
    {
        return _x.exchange(nullptr, std::memory_order::memory_order_relaxed);
    }
};

这篇关于围绕值变为空值的双重检查锁定?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

更多推荐

[db:关键词]

本文发布于:2023-04-30 16:22:58,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1396361.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:为空

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!