同时读取一个变量是线程安全的吗?

27
假设在读取期间变量不会被修改,那么一个变量同时被两个或更多线程读取会存在固有的问题吗?

在多线程编程中,假设变量始终处于被修改的风险状态可能更为安全。 - skukx
5个回答

21

该操作本身不具备线程安全性。

即使该变量当前没有被写入,对该变量之前的写入可能尚未对所有线程可见。这意味着两个线程可以读取相同的值并得到不同的结果,从而创建了一个竞争条件。

但是,通过内存屏障、正确使用volatile或其他几种机制可以防止这种情况发生。我们需要了解更多关于您的环境,特别是语言,才能给出完整的解释。

稍微修改一下你的问题能够得到更好的答案。假设没有更多的写入并且所有先前的写入对当前线程可见,则从多个线程读取该值是安全的。


虽然使用 volatile 取决于编程语言,但这是一个好的回答。在 C/C++ 中,volatile 是明显的假朋友,因为生成的代码非常与编译器相关,并且没有标准来说明 volatile 变量实际上应该做什么。 - zebrabox
@zebrabox,非常正确。我试图小心回答,因为它非常依赖于编程语言和平台。 - JaredPar
1
我正在尝试了解一个类似的问题,如果我有一个写入器进行增量操作,一个读取器读取该值,如果我不关心读取器在增量操作之前或之后读取该值,那么不使用锁和原子操作是否安全? - 1a1a11a
如果全局变量从未被写入(const),那么就没有问题,就我所知。 - ScienceDiscoverer

18

如果您的假设成立,那么就没有问题了。


问题不就在于确定他的假设是否成立吗?(可能并不成立,请参见guffa的答案:https://dev59.com/-3A75IYBdhLWcg3w6Nr8#3033439) - Kris
1
尽管当前没有写入操作,但之前的写入可能仍未对创建竞争条件的所有线程可见。请参阅我的答案以获取更多详细信息。 - JaredPar
2
@Kris,@JaredPar:确实如此,但我正在按照原帖的问题回答。 :-) - Platinum Azure

3
只要它是一个普通的变量,就没有风险。
如果它是一个属性,读取它可能会产生副作用,因此不能保证线程安全。

0

考虑到数据库通常可以使用共享读锁定,其中任意数量的客户端可以读取相同的块,我建议没有直接固有问题。


0

是的,用三个字母表示。

编辑: 哎呀,是的,它是线程安全的。不,没有问题。人们通常会问某个东西是否线程安全,而不是线程不安全。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接