Python 的整数类型是否线程安全?

8
Python的整数类型是线程安全的吗?我在谷歌上没有找到一个明确的答案。

8
现在你是否想要针对Python中的每种数据类型都问这个问题? - user2665694
@Sentinel:真正有趣的是那些保证了原子性但不保证线程安全的情况。 - Omnifarious
@Sentinel:在Python 3文档中非常模糊。 - lemiant
4
没有什么含糊不清的。元组、字符串和整数是不可变的已经是一个广为人知并且有文献证实的事实。因此,这里关于线程安全性的问题完全是毫无意义的。 - user2665694
但是,线程安全问题是“计算一个值并将其分配给共享变量是否线程安全?”这个问题的答案可能是“否”,对于某些情况下的“否”特别是涉及到共享变量的计算值时。 - lemiant
3个回答

11

是的,它们像字符串一样是不可变的。代码x += 1实际上创建一个全新的整数对象并将其赋值给x

如果不清楚的话,不可变的东西自动是线程安全的,因为两个线程无法同时尝试修改同一件事情。你看,它们不能被修改,因为它们是不可变的。

来自解释器的示例:

>>> x = 2**123
>>> x
10633823966279326983230456482242756608
>>> id(x)
139652080199552
>>> a = id(x)
>>> x+=1
>>> id(x)
139652085519488
>>> id(x) == a
False

18
在两个线程上同时执行x += 1操作可能会导致整数不安全,因为它不能保证是原子的(就像几乎所有其他语言一样)。在cPython中它很可能是原子的,因为有全局解释器锁(GIL),但这只是实现细节的副作用。 - Rosh Oxymoron
2
@Rosh Oxymoron:这是真的。但是线程安全问题是“计算一个值并将其分配给共享变量是否线程安全?”,这个答案会是“否”,对于一些“否”的情况,尤其是如果计算出来的值涉及到共享变量的时候。 - Omnifarious
所以,为了明确事情,简单访问共享 int 的值是线程安全的,对吗?当仅仅执行“print x”(其中 x 是共享变量)时,不存在损坏值的可能性。只有在更大操作或设置共享变量的上下文中,才需要考虑通过锁定来实现线程安全。 - papercrane
@papercrane - ints(像字符串和浮点数一样)是常量值。它们不能被修改。因此,在打印时,甚至根本不可能改变单个int的值。如果您谈论的是“x”的值。是的,它可以改变。但是您永远不会在“更改中间”看到它。它总是一件事或另一件事。但是由任何特定变量引用的int永远不会改变。在Python程序中,它绝对且完全是不可变的。 - Omnifarious

5

在Python中,Int是不可变的,这意味着它不能被修改,任何值的更改都是将一个新的不可变Int对象赋值给原始对象的过程。

但这并不意味着Python语法中的任何操作都是线程安全的,即使GIL也会受到影响。 例如:x+=1根本不是线程安全的。

为了确保代码的线程安全性,您需要找出对一个对象的操作是否是线程安全的。 对象本身并不保证线程安全,GIL也不保证。

参考: is += in python thread safe?


4

就像其他人所说的一样,Python对象大多数情况下是线程安全的。但是如果需要在一个地方保护一个对象,在它再次可用之前需要进行多次更改,则需要使用锁。


1
“Mostly thread-safe”这种说法并不能让人对构建大规模软件充满信心,语言实现规范应该更加明确。 - mosh
如果您想要线程安全,请使用锁并阅读文档以了解您所做的操作。当您在处理可能从这些线程访问相同数据的多个线程时,使用锁几乎是标准做法。 - maaudet

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