Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is Python variable assignment atomic?

Tags:

python

signals

Let's say I am using a signal handler for handling an interval timer.

def _aHandler(signum, _):   global SomeGlobalVariable   SomeGlobalVariable=True 

Can I set SomeGlobalVariable without worrying that, in an unlikely scenario that whilst setting SomeGlobalVariable (i.e. the Python VM was executing bytecode to set the variable), that the assignment within the signal handler will break something? (i.e. meta-stable state)

Update: I am specifically interested in the case where a "compound assignment" is made outside of the handler.

(maybe I am thinking too "low level" and this is all taken care of in Python... coming from an Embedded Systems background, I have these sorts of impulses from time to time)

like image 389
jldupont Avatar asked Feb 18 '10 18:02

jldupont


People also ask

Are assignments atomic in Python?

Operations like assignment and adding values to a list or a dict in Python are atomic.

Is assignment operator Atomic?

no, its not..... you need to use a locking primitive of some sort.

How are variables assigned in Python?

A variable is a string of characters and numbers associated with a piece of information. The assignment operator, denoted by the “=” symbol, is the operator that is used to assign values to variables in Python. The line x=1 takes the known value, 1, and assigns that value to the variable with name “x”.

Are Python variables created by assignment?

To summarize: Python lets you create variables simply by assigning a value to the variable, without the need to declare the variable upfront. The value assigned to a variable determines the variable type. Different types may support some operations which others don't.


2 Answers

Simple assignment to simple variables is "atomic" AKA threadsafe (compound assignments such as += or assignments to items or attributes of objects need not be, but your example is a simple assignment to a simple, albeit global, variable, thus safe).

like image 59
Alex Martelli Avatar answered Sep 19 '22 18:09

Alex Martelli


Google's Style Guide advises against it

I'm not claiming that Google styleguides are the ultimate truth, but the rationale in the "Threading" section gives some insight (highlight is mine):

Do not rely on the atomicity of built-in types.

While Python’s built-in data types such as dictionaries appear to have atomic operations, there are corner cases where they aren’t atomic (e.g. if __hash__ or __eq__ are implemented as Python methods) and their atomicity should not be relied upon. Neither should you rely on atomic variable assignment (since this in turn depends on dictionaries).

Use the Queue module's Queue data type as the preferred way to communicate data between threads. Otherwise, use the threading module and its locking primitives. Learn about the proper use of condition variables so you can use threading.Condition instead of using lower-level locks.

So my interpretation is that in Python everything is dict-like and when you do a = b in the backend somewhere globals['a'] = b is happening, which is bad since dicts are not necessarily thread safe.

For a single variable, Queue is not ideal however since we want it to hold just one element, and I could not find a perfect pre-existing container in the stdlib that automatically synchronizes a .set() method. So for now I'm doing just:

import threading  myvar = 0 myvar_lock = threading.Lock() with myvar_lock:     myvar = 1 with myvar_lock:     myvar = 2 

It is interesting that Martelli does not seem to mind that Google style guide recommendation :-) (he works at Google)

I wonder if the CPython GIL has implications to this question: What is the global interpreter lock (GIL) in CPython?

This thread also suggests that CPython dicts are thread safe, including the following glossary quote that explicitly mentions it https://docs.python.org/3/glossary.html#term-global-interpreter-lock

This simplifies the CPython implementation by making the object model (including critical built-in types such as dict) implicitly safe against concurrent access.