Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to share an integer between threads in python

I've got 2 threads:

  • A worker thread, that loops looking for input from an ssh socket
  • A manager thread, that processes stuff from the worker thread

They use a Queue to communicate - as stuff comes in, the worker places it on the Queue if it's important, and the manager takes it off to process.

However, I'd like the manager to also know the last time anything came in - whether important or not.

My thought was that the worker could set an integer (say), and the manager could read it. But there doesn't seem to be a threading primitive that supports this.

Is it safe for the manager to just read the worker's instance variables, providing it doesn't write to them? Or will that give some shared memory issues? Is there some way I can share this state without putting all the junk stuff in the Queue?

like image 806
xorsyst Avatar asked Sep 16 '25 12:09

xorsyst


1 Answers

Is it safe for the manager to just read the worker's instance variables, providing it doesn't write to them?

Yes, this is safe in CPython. Because of the GIL, it's impossible for one thread to be reading the value of a variable while another thread is in process of writing it. This is because both operations are a single bytecode instruction, which makes them atomic - the GIL will be held for the entire instruction, so no other thread can be executing at the same time. One has to happen either before or after the other. You'll only run into issues if you have two different threads trying to do non-atomic operations on the same object (like incrementing the integer, for example). If that were the case, you'd need to use a threading.Lock() that was shared between the two threads to synchronize access to the integer.

Do note that the behavior of bytecode (and even the existence of the GIL) is considered an implementation detail, and is therefore subject to change:

CPython implementation detail: Bytecode is an implementation detail of the CPython interpreter! No guarantees are made that bytecode will not be added, removed, or changed between versions of Python.

So, if you want to be absolutely safe across all versions and implementations of Python, use a Lock, even though it's not actually necessary right now (and in reality, probably won't ever be) in CPython.

Using a Lock to synchronize access to a variable is very straightforward:

lock = threading.Lock()

Thread 1:

with lock:
   print(shared_int)  # Some read operation
# Lock is release once we leave the with block

Thread 2:

with lock:
   shared_int = 55 # Some write operation
like image 83
dano Avatar answered Sep 19 '25 05:09

dano