Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typo3/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用python多线程时是否需要锁?_Python_Multithreading - Fatal编程技术网

使用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)