Python 实例变量的线程问题
所以我似乎误解了Python的一些基本内容。将实例变量传递到函数中应该只传递对对象本身的引用,因此在对象不可变的情况下,可以执行类似于Python 实例变量的线程问题,python,multithreading,thread-safety,python-3.x,Python,Multithreading,Thread Safety,Python 3.x,所以我似乎误解了Python的一些基本内容。将实例变量传递到函数中应该只传递对对象本身的引用,因此在对象不可变的情况下,可以执行类似于self.var=“something”的操作;foo(self.var)如果foo给变量分配了一个新的值,就不应该更改self.var——只要一切正常并且符合预期 但现在考虑一下: import threading class Test(): def __init__(self): self.lock = threading.Lock(
self.var=“something”的操作;foo(self.var)
如果foo给变量分配了一个新的值,就不应该更改self.var——只要一切正常并且符合预期
但现在考虑一下:
import threading
class Test():
def __init__(self):
self.lock = threading.Lock()
self.arg = "arg0"
def foo(self, i):
with self.lock:
threading.Thread(target=lambda: bar(self.arg)).start()
self.arg = "arg" + str(i)
def bar(arg):
import time
time.sleep(1)
print("Bar: " + arg)
if __name__ == '__main__':
t = Test()
for i in range(1, 6):
t.foo(i)
我创建了一个线程对象,引用了当前字符串,然后更新了它——线程不应该看到它。多亏了锁,下一个线程也应该只在更新后启动——因此,虽然我不能对arg0-5的打印顺序做出任何假设,但我会假设每个arg都应该精确打印一次。但是我得到了以下输出(win7x64,python3.1x64)
编辑:好的,在输入这个之后,我有了一个很好的想法,创建线程时可能不会执行lambda表达式,但稍后会执行,这将解释行为,因此简单的解决方法是只创建一个局部变量并使用它。好吧,这是苏的快速帮助;) 因为我注意到我还没有回答这个问题,我们开始:
lambda创建了一个对
self
的闭包,而不是对self.arg
本身的闭包,这意味着当我们稍后执行bar时,我们访问的是最新的值,而不是lambda创建时的值。恭喜!你解开了这个谜。另一件事:你认为类测试():
做什么,而不是类测试:
或类测试(对象):
?@pillmuncher:我使用的是Python3,所以幸运的是,我不必担心旧类和新类。虽然我不知道类测试:
是合法语法-这样更好一些,很棒(对于python2来说,它仍然默认为旧的类语法,不是吗?@Voo如果你解决了自己的问题,把它作为答案发布,两天后你就可以接受它了。
Bar: arg0
Bar: arg2
Bar: arg2
Bar: arg5
Bar: arg3