mri*_*rip 6 python multithreading volatile memory-barriers
我想知道 Java 的“易失性”的等价物,并找到了这个答案。
这(基本上)表明,由于 GIL,Python 中的所有内容实际上都是易变的,至少在 CPython 中是这样。这是有道理的,一切都被 GIL 锁定,没有内存障碍需要担心,等等。但如果这是由规范记录和保证的,我会更高兴,而不是让它成为 cpython 目前碰巧的方式的结果实施的。
因为,假设我希望一个线程发布数据,其他线程读取数据,所以我可以选择这样的内容:
class XFaster:
def __init__(self):
self._x = 0
def set_x(self, x):
self._x = x
def get_x(self, x):
return self._x
class XSafer:
def __init__(self):
self._x = 0
self._lock = threading.Lock()
def set_x(self, x):
with self._lock:
self._x = x
def get_x(self, x):
with self._lock:
return self._x
Run Code Online (Sandbox Code Playgroud)
我宁愿使用XFaster甚至根本不使用 getter 和 setter。但我也想可靠地、“正确地”做事。有没有一些官方文档说这是可以的?比如说在 a 中添加一个值dict或附加到 a 上怎么样list?
换句话说,是否有一种系统的、记录在案的方法来确定我可以在没有 a 的情况下做什么threading.Lock(无需深入挖掘dis或类似的东西)?并且最好不会与未来的 python 版本发生冲突。
编辑时:我很欣赏评论中的知情讨论。但我真正想要的是一些保证以下内容的规范:
如果我执行这样的事情:
# in the beginning
x.a == foo
# then two threads start
# thread 1:
x.a = bar
# thread 2
do_something_with(x.a)
Run Code Online (Sandbox Code Playgroud)
我想确定的是:
x.a它读取foo或者barbar以下是我不想发生的一些事情:
x.a=bar线程 1 的分配对线程 2 不可见x.__dict__正在重新散列,因此线程 2 读取垃圾TLDR:CPython 保证其自己的数据结构是线程安全的,不会损坏。这并不意味着任何自定义数据结构或代码都是无竞争的。
\nGIL 的目的是保护 CPython 的数据结构免遭损坏。人们可以信赖内部状态是线程安全的。
\n\n\n全局解释器锁(Python 文档 \xe2\x80\x93 术语表)
\n
\n\nCPython 解释器用来确保一次只有一个线程执行 Python 字节码的机制。这通过使对象模型(包括关键内置类型,例如 dict)针对并发访问隐式安全,简化了 CPython 实现。[...]
\n
这也意味着跨线程的更改的正确可见性。
\n然而,这并不意味着任何独立的语句或表达式都是原子的:几乎任何语句或表达式都可以调用多个字节码指令。因此,GIL 明确不为这些情况提供原子性。
\n具体来说,诸如 之类的语句x.a=bar可以通过经由object.__setattr__描述符协议调用设置器来执行任意多个字节码指令。它至少执行三个字节码指令,用于bar查找、x查找和a赋值。
因此,Python保证可见性/一致性,但不提供针对竞争条件的保证。如果一个对象同时发生变化,则必须对其进行同步以确保正确性。
\n| 归档时间: |
|
| 查看次数: |
672 次 |
| 最近记录: |