gpt4 book ai didi

c++ - const 在 C++11 中是否意味着线程安全?

转载 作者:IT老高 更新时间:2023-10-28 11:51:15 27 4
gpt4 key购买 nike

我听说const在 C++11 中意味着线程安全。这是真的吗?

这是否意味着 const现在相当于 Java 的 synchronized ?

他们的关键字用完了吗?

最佳答案

I hear that const means thread-safe in C++11. Is that true?


有点 真的...
这就是标准语言关于线程安全的说法:

[1.10/4]Two expression evaluations conflict if one of them modifies a memory location (1.7) and the other one accesses or modifies the same memory location.

[1.10/21]The execution of a program contains a data race if it contains two conflicting actions in different threads, at least one of which is not atomic, and neither happens before the other. Any such data race results in undefined behavior.


这只不过是发生数据竞争的充分条件:
  • 对给定事物同时执行两个或多个 Action ;和
  • 其中至少一个是写入。

  • 标准库以此为基础,更进一步:

    [17.6.5.9/1]This section specifies requirements that implementations shall meet to prevent data races (1.10). Every standard library function shall meet each requirement unless otherwise specified. Implementations may prevent data races in cases other than those specified below.

    [17.6.5.9/3]A C++ standard library function shall not directly or indirectly modify objects (1.10) accessible by threads other than the current thread unless the objects are accessed directly or indirectly via the function’s non-const arguments, including this.


    简单地说,它期望对 const 进行操作。对象是线程安全的。这意味着只要在 const 上进行操作,标准库就不会引入数据竞争。您自己类型的对象
  • 完全由读取组成——也就是说,没有写入——;或
  • 在内部同步写入。

  • 如果这种期望不适用于您的一种类型,那么直接或间接将它与标准库的任何组件一起使用可能会导致数据竞争。总之, const从标准库的角度来看,确实意味着线程安全。重要的是要注意,这只是一个契约(Contract),编译器不会强制执行,如果你违反它,你会得到未定义的行为,你是自己的。是否 const存在与否不会影响代码生成——至少不会影响数据竞争——。

    Does that mean const is now the equivalent of Java's synchronized?


    .一点也不...
    考虑以下表示矩形的过于简化的类:
    class rect {
    int width = 0, height = 0;

    public:
    /*...*/
    void set_size( int new_width, int new_height ) {
    width = new_width;
    height = new_height;
    }
    int area() const {
    return width * height;
    }
    };
    成员函数 area是线程安全的;不是因为它的 const ,但因为它完全由读取操作组成。不涉及写入,并且至少需要涉及一次写入才能发生数据竞争。这意味着您可以拨打 area从任意多的线程中获取,您将始终获得正确的结果。
    请注意,这并不意味着 rect是线程安全的。事实上,如果拨打 area 很容易看出如何。与拨打 set_size 的同时发生在给定的 rect ,然后 area最终可能会根据旧的宽度和新的高度(甚至是乱码)计算其结果。
    不过没关系, rect不是 const所以它甚至不希望是线程安全的。声明的对象 const rect ,另一方面,将是线程安全的,因为不可能写入(如果您正在考虑 const_cast -ing 最初声明的东西 const 那么您会得到未定义的行为,就是这样)。

    So what does it mean then?


    让我们假设——为了论证——乘法运算的成本非常高,我们最好尽可能避免它们。我们可以仅在请求时计算该区域,然后将其缓存以备将来再次请求时:
    class rect {
    int width = 0, height = 0;

    mutable int cached_area = 0;
    mutable bool cached_area_valid = true;

    public:
    /*...*/
    void set_size( int new_width, int new_height ) {
    cached_area_valid = ( width == new_width && height == new_height );
    width = new_width;
    height = new_height;
    }
    int area() const {
    if( !cached_area_valid ) {
    cached_area = width;
    cached_area *= height;
    cached_area_valid = true;
    }
    return cached_area;
    }
    };
    [如果这个例子看起来太人为,你可以在心里替换 int由一个非常大的动态分配的整数组成,该整数本质上是非线程安全的,并且乘法成本极高。]
    成员函数 area不再是线程安全的,它现在正在写入并且不在内部同步。有问题吗?调用 area可能作为另一个对象的复制构造函数的一部分发生,这样的构造函数可能已被标准容器上的某些操作调用,并且在这一点上,标准库希望此操作在数据竞争方面表现为读取。但我们正在写!
    一旦我们放了 rect在标准容器中——直接或间接——我们正在与标准库签订契约(Contract)。继续写 const在仍然遵守该契约(Contract)的同时,我们需要在内部同步这些写入:
    class rect {
    int width = 0, height = 0;

    mutable std::mutex cache_mutex;
    mutable int cached_area = 0;
    mutable bool cached_area_valid = true;

    public:
    /*...*/
    void set_size( int new_width, int new_height ) {
    if( new_width != width || new_height != height )
    {
    std::lock_guard< std::mutex > guard( cache_mutex );

    cached_area_valid = false;
    }
    width = new_width;
    height = new_height;
    }
    int area() const {
    std::lock_guard< std::mutex > guard( cache_mutex );

    if( !cached_area_valid ) {
    cached_area = width;
    cached_area *= height;
    cached_area_valid = true;
    }
    return cached_area;
    }
    };
    请注意,我们制作了 area函数线程安全,但 rect仍然不是线程安全的。调用 area与此同时,有人接到了 set_size 的电话。由于对 width 的赋值,最终可能仍会计算出错误的值。和 height不受互斥锁保护。
    如果我们真的想要一个线程安全的 rect ,我们将使用同步原语来保护非线程安全 rect .

    Are they running out of keywords?


    是的,他们是。从第一天起,他们的关键字就用完了。

    来源: You don't know const and mutable - Vanilla 萨特

    关于c++ - const 在 C++11 中是否意味着线程安全?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14127379/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com