There's also the possibility to use shared ctypes:
https://docs.python.org/3/library/multiprocessing.html#shared-ctypes-objects

Operations like += which involve a read and write are not atomic. So if, for instance, you want to atomically increment a shared value it is insufficient to just do
counter.value += 1
 
Assuming the associated lock is recursive (which it is by default) you can instead do

with
counter.get_lock(): counter.value += 1

Notice that they use a lock anyway. Maybe the solution of Wes Turner is better. See also RLock:
https://docs.python.org/3/library/multiprocessing.html#multiprocessing.RLock

On Sat, 1 Aug 2020 at 22:42, Eric V. Smith <eric@trueblade.com> wrote:
While they're immutable at the Python level, strings (and all other
objects) are mutated at the C level, due to reference count updates. You
need to consider this if you're sharing objects without locking or other
synchronization.


This is interesting. What if you want to have a language that uses only immutable objects and garbage collection? Could smart pointers address this problem?