我有多个线程访问同一个类变量,如果其中一个线程对类变量进行了更改,那么当其他线程访问该变量时,更改是否会反映出来? 还是为每个线程创建类的副本?因为如果是这种情况,那么更改将不会得到体现。
答案 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)
当您说一个类变量时,是指实例变量还是类变量?您必须同步读写访问才能使其对其他线程可见。