【问题标题】:Is it safe to read(only) the same non-atomic variable in different threads without locking?在不锁定的情况下在不同线程中读取(仅)相同的非原子变量是否安全?
【发布时间】:2021-10-03 14:15:40
【问题描述】:

我有一个类方法,我想在不同的线程中同时读取相同的非原子类成员。该方法是const,因此它不会写入正在读取的成员。在这种情况下不用担心任何锁是否安全?

编辑: 我应该举个例子:

class SomeClass()
{
    public:
        void someMethod() const;
//...
    private:
        std::string someMemeber_; // might be changed by some methods
//...
}

void SomeClass::someMethod() const
{
    std::jthread thr1([](){/*read someMember_ here*/});
    std::jthread thr2([](){/*read someMember_ here*/});
//...
}

【问题讨论】:

  • 类实例化后,成员的值可以改变吗?
  • 可以,可以通过其他方法改变该值,但不能在多线程方法执行过程中。
  • 那么每当值发生变化时,每个读取线程都需要至少同步一次。
  • 如果代码向变量写入一个值,然后启动一堆只读取该值的线程,而在这些线程运行时没有其他人修改它,则代码没有数据竞争。

标签: c++ multithreading thread-safety


【解决方案1】:

这是安全的,前提是你可以保证正在读取的数据在多个线程不同步访问期间不会改变。

(请注意,这段时间不仅包括线程 调用您的 const 方法的短暂时刻,还包括线程可以调用的整个时间区域你的 const 方法。因此,例如在许多程序中,这个不允许修改的时期可能开始于第一个子线程产生的那一刻,并在最后一个子线程退出并成为 join() 的那一刻结束d)

【讨论】:

    【解决方案2】:

    鉴于:

    是的,可以通过其他方法更改该值,但不能在多线程的方法执行期间进行。

    盲目地读取可能被其他线程修改的非原子值是本质上安全的,即使您 100% 确定不会在读取的同时发生任何修改。

    在从读取线程中看到修改之前,两个线程之间必须有同步

    潜在的问题不仅仅是读取过时的值。如果编译器可以确定在同一内存位置的两次后续读取之间没有发生同步,则完全允许只读取一次并缓存结果。

    有多种方法可以完成同步,在给定场景中哪种方法最好取决于上下文。

    查看https://en.cppreference.com/w/cpp/language/memory_model了解更多详情

    但是,一旦建立同步,任意数量的线程都可以同时从同一内存位置读取。

    【讨论】:

      【解决方案3】:

      我有一个类方法,我想在不同的线程中同时读取相同的非原子类成员。该方法是 const,因此它不会写入正在读取的成员。在这种情况下不用担心任何锁是否安全?

      是的,它是 100% 安全的。我假设唯一的问题是多个线程正在读取并且如果单个线程正在读取代码将是安全的。额外的线程正在读取相同的数据对读取是否安全没有影响。

      数据竞争只能发生在读取和修改之间。因此,如果一个线程的一次读取不会与任何修改竞争,那么额外的读取也不会。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-23
        • 1970-01-01
        • 1970-01-01
        • 2017-05-15
        • 2014-02-25
        • 2023-02-13
        相关资源
        最近更新 更多