好的,请先检查以下代码:
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()
我面临与上述相同的情况。我真的想知道self.Counter
是否是线程安全的,如果没有,我有什么选择?我只能想到threading.RLock()
来锁定这个资源,还有更好的主意吗?
答案 0 :(得分:31)
您可以使用锁定,RLocks,信号量,条件,事件和队列 这篇文章帮助我很多 看看:Laurent Luce's Blog
答案 1 :(得分:22)
使用实例字段self.Counter
为thread safe or "atomic"。读取它或分配单个值 - 即使它在内存中需要4个字节,你也永远不会得到一个半变化的值。但是操作self.Counter = self.Counter + 1
不是因为它读取值然后写入它 - 另一个线程可以在读取之后和写回之前更改字段的值。
所以你需要用锁来保护整个操作。
由于方法体基本上是整个操作,因此可以使用装饰器来完成此操作。请参阅此答案以获取示例:https://stackoverflow.com/a/490090/34088
答案 2 :(得分:9)
不,它不是线程安全的 - 两个线程实际上是同时修改同一个变量。是的,该解决方案是threading
模块中的锁定机制之一。
BTW,self.Counter
是实例变量,而不是类变量。
答案 3 :(得分:1)
self.Counter
是一个实例变量,因此每个线程都有一个副本。
如果在__init__()
之外声明变量,它将是一个类变量。
该类的所有实例都将共享该实例。
答案 4 :(得分:0)
Atomos 库为 Python 原语和对象(包括原子计数器)提供原子(线程安全)包装器。它使用单写入器/多读取器锁。