Each Answer to this Q is separated by one/two green lines.
OK, check following codes first:
class DemoClass(): def __init__(self): #### I really want to know if self.Counter is thread-safe. self.Counter = 0 def Increase(self): self.Counter = self.Counter + 1 def Decrease(self): self.Counter = self.Counter - 1 def DoThis(self): while True: Do something if A happens: self.Increase() else: self.Decrease() time.sleep(randomSecs) def DoThat(self): while True: Do other things if B happens: self.Increase() else: self.Decrease() time.sleep(randomSecs) def ThreadSafeOrNot(self): InterestingThreadA = threading.Thread(target = self.DoThis, args = ()) InterestingThreadA.start() InterestingThreadB = threading.Thread(target = self.DoThat, args = ()) InterestingThreadB.start()
I’m facing same situation as above. I really want to know if it’s thread-safe for
self.Counter, well if not, what options do I have? I can only think of
threading.RLock() to lock this resource, any better idea?
You can use Locks, RLocks, Semaphores, Conditions, Events and Queues.
And this article helped me a lot.
Check it out: Laurent Luce’s Blog
Using the instance field
self.Counter is thread safe or “atomic”. Reading it or assigning a single value – even when it needs 4 bytes in memory, you will never get a half-changed value. But the operation
self.Counter = self.Counter + 1 is not because it reads the value and then writes it – another thread could change the value of the field after it has been read and before it is written back.
So you need to protect the whole operation with a lock.
Since method body is basically the whole operation, you can use a decorator to do this. See this answer for an example: https://stackoverflow.com/a/490090/34088
No, it is not thread safe – the two threads are essentially modifying the same variable simultaneously. And yes, the solution is one of the locking mechanisms in the
self.Counter is an instance variable, not a class variable.
self.Counter is an instance variable, so each thread has a copy.
If you declare the variable outside of
__init__(), it will be a class variable.
All instances of the class will share that instance.
The Atomos library provides atomic (thread-safe) wrappers for Python primitives and objects, including atomic counters. It uses single-writer/multiple-reader locks.