Python 中与 Java volatile 相等的变量

25

Python中是否有与Java volatile 概念相当的东西?

在Java中有一个关键字volatile。据我所知,当我们在声明变量时使用volatile,那么对该变量值的任何更改将对同时运行的所有线程可见。

我想知道在Python中是否有类似的东西,这样当一个变量的值在一个函数中被改变时,它的值将对同时运行的所有线程可见。

2个回答

46
据我所知,当我们在变量声明时使用volatile关键字,该变量的任何更改都将对同时运行的所有线程可见。 volatile比这个复杂一些。 volatile确保Java将变量值存储和更新在主内存中。如果没有volatile,JVM可以自由地将值存储在CPU缓存中,这会导致对值的更新在不同CPU核上运行的不同线程(在同一个核上并发运行的线程看到该值)看不到。
Python从不这样做。 Python将所有对象存储在堆中,即主内存中。此外,由于Python解释器循环如何使用锁定(GIL),每次只有一个线程会活跃地运行Python代码。永远不存在不同线程在不同CPU上运行Python解释器循环的情况。
因此,在Python中您无需使用volatile,因为不存在这样的概念,并且您不必担心它。

3
有趣。这会使得某些多线程应用程序的Python运行变慢吗? - Dici
GIL不就是CPython的一种实现吗? - Mark Rotteveel
1
@Dici:是的,CPython不能并行运行Python代码,只能并发运行。(从Python生成的本地代码不受此限制,因此numpy和其他扩展程序不受此限制)。 - Martijn Pieters
3
是的,但 IronPython、Jython 和 PyPy 也没有 volatile,因为它们也只是在堆上使用对象。 - Martijn Pieters
3
在单个CPU上快速在线程之间切换意味着这些线程是并发运行的。在两个不同CPU核心上同时运行两个线程意味着它们是并行运行的。Python只能做前者。 - Martijn Pieters
显示剩余6条评论

-5
关键字"global"就是你要找的:
import threading

queue = []
l = threading.Lock()

def f():
    global queue
    l.acquire()
    queue.append(1)
    l.release()

def g():
    print(queue)

threads = [
    threading.Thread(target=f),
    threading.Thread(target=g)
]
for t in threads:
    t.start()
for t in threads:
    t.join()

谢谢,你的代码中 queue = [] 怎么样?由于它在所有函数之外声明,它不也被视为全局变量吗? - Pablo
关键字 global 的作用是允许您修改程序中其他地方绑定的变量。如果不这样做,您只能对其进行“读取”访问。 - Oyono
4
这与“全局”无关。 OP所讨论的问题同样适用于Python实例属性,这些属性在Python中完全可见,并且可以在Java中设置为“public”。 - Martijn Pieters
2
此外,由于您在代码中从未尝试绑定到“queue”名称,因此“global queue”语句完全是多余的。它可以从您的示例中删除,而不会影响行为。 - Martijn Pieters

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