使用python多线程时是否需要锁?
想想这个代码:使用python多线程时是否需要锁?,python,multithreading,Python,Multithreading,想想这个代码: #!/usr/bin/env python from threading import Thread count = 0 def test(): global count for i in range(10): count = count + 1 if __name__ == '__main__': for i in range(1000): Thread(target = test).start() pri
#!/usr/bin/env python
from threading import Thread
count = 0
def test():
global count
for i in range(10):
count = count + 1
if __name__ == '__main__':
for i in range(1000):
Thread(target = test).start()
print count
我使用多个线程,但结果总是正确的。这是否意味着我可以在实现访客计数器之类的东西时使用不带锁的python线程?您确实需要一个。尽管多线程在Python中的工作方式有所不同,但由于内存不足,Python字节码中非原子的操作仍然需要锁定 在您的情况下,您可以检查功能的字节码
test
(dis.dis(test)
):
正如您所看到的,增量是字节码级别的2xload、update和store,所以这不起作用。增量实际上是4个独立的操作,您必须保护它们以确保它们不会被中断
在您的示例中,即使使用count+=1
,问题仍然存在,如字节码所示:
4 19 LOAD_GLOBAL 1 (count)
22 LOAD_CONST 2 (1)
25 INPLACE_ADD
26 STORE_GLOBAL 1 (count)
当然你应该用锁。在这种简单的情况下,你得到了正确的答案。尝试将其设置为main中的范围(100000)。你会发现问题所在。在我的机器中,结果是999960,但它是随机结果。根据系统负载等情况,会出现错误。如果您只是执行分配,则不需要锁定 但是当您执行
count=count+1
时,在读取count
、添加1
和写入count
之间可能会发生一些事情
即使使用
count+=1
也不能解决这个问题,因为这也涉及到赋值。(由于现场操作也涉及机罩下的任务,情况也是一样。)我不确定,但你应该尝试更大的数字。你是对的,我使用100000个线程,但它失败了。您可以使用Queue be,因为这是处理本机python线程的最简单的方法。count+=1只是count=count+1So的一个同步糖,想象一下当一个线程开始读取count的值以增加它,而另一个线程正在增加它时的情况,第一个线程写相同的数字,这是一个竞争条件问题。@crow16384一般来说,你的陈述是错误的:在列表上尝试一下,你会发现不同之处。在字节码中,它使用INPLACE\u ADD
而不是BINARY\u ADD
。但是,对于int和其他不可变对象,这一点是正确的,因为缺少。\uuuu iadd\uuu()
,调用求助于。\uuu add\uuuu()
。一般来说,我关于count+=1等于count=count+1的陈述是错误的,但这里讨论的是整数。
4 19 LOAD_GLOBAL 1 (count)
22 LOAD_CONST 2 (1)
25 INPLACE_ADD
26 STORE_GLOBAL 1 (count)