在不加锁的情况下,在不同的线程中读取(仅)相同的非原子变量是否安全?



我有一个类方法,我想在不同线程中同时读取相同的非原子类成员。该方法是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*/});
//...
}

这是安全的,只要您可以保证在多个线程对其进行非同步访问期间正在读取的数据不会更改。

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

鉴于:

是,该值可以被其他方法更改,但不能在多线程执行该方法时更改。

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

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

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

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

详情请参阅https://en.cppreference.com/w/cpp/language/memory_model

然而,一旦建立了同步,任何数量的线程都可以并发地从同一内存位置读取数据。

我有一个类方法,我想在不同线程中同时读取相同的非原子类成员。该方法是const,所以它不会写入被读取的成员。这种情况下不用锁安全吗?

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

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