关于多线程:Python实例变量是否是线程安全的?

Are Python instance variables thread-safe?

好的,首先检查以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
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()来锁定这个资源,有什么更好的主意吗?


您可以使用锁、rlocks、信号量、条件、事件和队列。这篇文章对我帮助很大。看看:劳伦特·卢斯的博客


使用实例字段self.Counter是线程安全的或"原子的"。读取或分配一个值-即使它需要4个字节的内存,也永远不会得到半个更改的值。但是操作self.Counter = self.Counter + 1并不是因为它先读取值,然后再写入值——另一个线程可能会在字段被读取之后和被写回之前更改该字段的值。

所以你需要用锁来保护整个操作。

因为方法体基本上是整个操作,所以可以使用修饰符来完成这项操作。请参阅此答案获取示例:https://stackoverflow.com/a/49090/34088


不,这不是线程安全的-两个线程本质上是同时修改同一个变量。是的,解决方案是threading模块中的锁定机制之一。

btw,self.Counter是一个实例变量,而不是类变量。


self.counter是一个实例变量,因此每个线程都有副本。如果您在uu init()之外声明变量,它将是一个类变量。类的所有实例都将共享该实例。