I have an immutable object (a float
) that is "written" by one thread and read by another one. Do I need synchronization for that?
class Foo:
def __init(self):
self._bar = None
def writeAttribute(self, newValue):
self._bar = newValue
def readAttribute(self):
return self._bar
Note that writeAttribute
and readAttribute
are called from different threads for the same instance. My understanding is that readAttribute
returns a "reference" either to the old value or the new one, but nothing in between.
In CPython (the one from python.org
) the Global Interpreter Lock ("GIL") ensures that only one thread at a time is executing Python bytecodes. Also, threads can be preempted in between bytecodes, but not "inside" them. That means bytecodes are atomic.
That means that every action that takes a single bytecode is thread-safe as a side-effect of the GIL.
Consider the following code, were the dis
module is used to see bytecodes for a function:
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
Assigning a new value to the global bar
takes only a single STORE_GLOBAL
bytecode. So that should be thread-safe, in the sense that bar
always points to an object. Its value is never undetermined.
Of note; it doesn't matter that a float
object is immutable. The reference to that object (bar
in the example) is mutable. It is that reference that you want to keep defined and unambiguous.
Second, instead of a getter/setter method in your class Foo
I would propose that you use @property decorator. It is considered more Pythonic.
Edit
See also the FAQ: What kinds of global value mutation are thread-safe?
Edit2
Of course: when in doubt, use e.g. a Lock
.