我需要对不可变对象进行同步吗?

Do I need synchronization for immutable objects?

我有一个不可变对象 (float),它由一个线程“写入”并由另一个线程读取。我需要同步吗?

class Foo:
   def __init(self):
      self._bar = None

   def writeAttribute(self, newValue):
      self._bar = newValue

   def readAttribute(self):
      return self._bar

请注意,writeAttributereadAttribute 是从同一实例的不同线程调用的。我的理解是 readAttribute returns 是对旧值或新值的“参考”,但介于两者之间。

在 CPython(来自 python.org 的那个)中,全局解释器锁(“GIL”)确保一次只有一个线程在执行Python字节码。此外,线程可以在字节码之间被抢占,但不能在它们“内部”被抢占。这意味着字节码是 atomic.

这意味着每个采用单个字节码的操作都是 thread-safe 作为 GIL 的 side-effect

考虑以下代码,dis 模块用于查看函数的字节码:


In [2]: bar = 3.14
Out[2]: 3.14

In [3]: def modify(new):
   ...:     global bar
   ...:     bar = new
   ...:     

In [4]: dis.dis(modify)
  3           0 LOAD_FAST                0 (new)
              2 STORE_GLOBAL             0 (bar)
              4 LOAD_CONST               0 (None)
              6 RETURN_VALUE

为全局 bar 分配一个新值只需要一个 STORE_GLOBAL 字节码。所以这应该是 thread-safe,因为 bar 总是指向一个对象。它的价值永远是不确定的。

注意; float 对象是不可变的并不重要。该对象的引用(示例中的bar可变的。这是您要保持定义和明确的参考。

其次,我建议您使用 @property 装饰器,而不是 class Foo 中的 getter/setter 方法。算是比较Pythonic.

编辑

另请参阅常见问题解答:What kinds of global value mutation are thread-safe?

编辑2

当然:如有疑问,请使用例如Lock.