当多个线程访问一个类变量时,该变量是否对所有线程都通用?

时间:2019-07-19 14:36:59

标签: python sockets python-multithreading

我有多个线程访问同一个类变量,如果其中一个线程对类变量进行了更改,那么当其他线程访问该变量时,更改是否会反映出来? 还是为每个线程创建类的副本?因为如果是这种情况,那么更改将不会得到体现。

3 个答案:

答案 0 :(得分:1)

python中的所有线程(threading.Thread)共享相同的全局范围。

因此您可以执行以下操作:

from threading import Thread

class foobar:
    def __init__(self, value):
        self.value = value


def foo(inst):
    print(inst.value)
    inst.value = 1337

inst = foobar(42)
thread = Thread(target=foo, args=[inst])
thread.start()
thread.join()
print(inst.value)

将打印42,然后打印1337

不过,您需要注意,在python中,默认情况下读写是原子的,例如:

value = 12

print(value)

将正常工作,在执行以下更复杂的操作时会遇到问题:

value = value + 1

不再是线程安全的,因为它先读取值然后写入它。 为了使这项工作有效,您需要使用锁/互斥锁。

请查看Python Thread Synchronization,以获取有关python中的线程和锁的全面指南。

答案 1 :(得分:0)

类变量在类本身上更新。这意味着该类的所有实例都将看到更改。如果这是所需的行为,则可以使用类变量,但是,如果该变量应保存实例的特定数据,请使用实例变量。

class MyClass:
    # This should not be used unless you understand how class variables
    # work.
    class_var = 'foo'

    def __init__(self):
        self.bar = 'bar' # All threads can read and write to this.

这是一个示例,说明更新类变量可能会产生意外的后果。

class Foo:
    bar = 'baz'

a = Foo()          # First instance created.
a.bar              # 'baz'
Foo.bar = 'spam'   # Class variable update happens.
b = Foo()          # Second instance is created.
b.bar              # 'spam'

如果在同一类的实例化之间更改了类变量,则覆盖的名称将“继承”到新实例。这应该很明显,因为第二个实例是在更新其属性后使用该类创建的。

但是看看这个:

print(a.bar)
print(b.bar)

打印:

spam
spam

我们也更改了第一个实例的bar属性。尽管很明显更新Foo.bar会影响第二个实例上的bar(因为它是在实例化之前定义的),但对于在之前< / em> class属性已更新。

在多线程的情况下-如果线程更新了一个类变量,则每个线程的更新将影响该类的所有其他实例。如果不希望这样做,请改用实例变量。

答案 2 :(得分:-1)

当您说一个类变量时,是指实例变量还是类变量?您必须同步读写访问才能使其对其他线程可见。