2010-02-09 27 views

回答

39

您需要为所有将在Python中修改的共享变量实现自己的锁定。你不必担心从不会被修改的变量(即并发读取可以)读取数据,所以不可变类型(frozenset,tuple,str)是,可能是安全的,但它不会受到伤害。对于你将要改变的东西 - list,set,dict和大多数其他对象,你应该有自己的锁定机制(虽然就地操作对大多数这些都是可以的,但是线程会导致超级讨厌的错误 - 你可能还会实现锁定,这很容易)。

顺便说一句,我不知道你是否知道这一点,但锁定在Python很容易 - 创建一个threading.lock对象,然后你可以获取/释放它是这样的:

import threading 
list1Lock = threading.Lock() 

with list1Lock: 
    # change or read from the list here 
# continue doing other stuff (the lock is released when you leave the with block) 

在Python 2.5中,请执行from __future__ import with_statement; Python的2.4和之前没有这个,所以你会希望把采集()/释放()调用try:...finally:块:

​​

Some very good information about thread synchronization in Python

+12

我相信,对于之前没有使用过线程锁的人来说,应该注意的是锁(在你的例子中,'list1Lock')应该在线程之间共享*,以便它能够正常工作。两个独立的锁,每个线程一个锁,什么都不会锁,只会增加傻瓜的开销。 – tzot 2010-02-18 08:44:53

+0

不应该是这样: with list1Lock:#做东西 – 2011-05-20 08:09:49

+0

@ slack3r良好的调用! – 2011-05-20 17:59:55

3

只要您不禁用线程的C代码中的GIL,它们就是线程安全的。

+5

这是CPython的实现细节,你不应该继续。将来可能会有机会,其他实现也没有。 – 2010-02-09 06:32:36

+0

格奥尔格 - 蟒蛇的这种方式阻止我。当8核心在桌面上变得常见时,不要介意所有会从Java程序中退出的错误 - 当GIL被移除并且多线程Python应用突然在8核心盒子上运行时会发生什么? – Ben 2010-02-09 12:11:04

+3

如果他们不明白自己的代码是否是线程安全的,那么它不应该吓倒任何人。 :) – Kylotan 2010-02-09 15:12:16

7

是的,但你仍然需要小心,当然

。例如:

如果两个线程都从列表中只有一个项目竞相pop(),一个线程将成功获得该项目和其他将得到一个IndexError

这样的代码是不是线程安全的

if L: 
    item=L.pop() # L might be empty by the time this line gets executed 

你应该WR像这样迭代它

try: 
    item=L.pop() 
except IndexError: 
    # No items left 
+5

我想弹出()是线程安全的,但我无法在文档中的任何位置找到这个事实。在我把它作为福音之前,有人能帮我找出这个说法吗? – 2012-03-28 13:12:41

+0

真的吗? list.pop()不是线程安全的?我看到另一篇文章宣称相反。 http://effbot.org/pyfaq/what-kinds-of-global-value-mutation-are-thread-safe.htm – 2016-10-03 18:50:34

+0

@ Zhongjun'Mark'Jin他说它是线程安全的..但这并不意味着你不必考虑其他线程。如果一个线程弹出最后一个项目,然后另一个线程尝试弹出,它会得到IndexError,正如他所说的。 – fantabolous 2016-12-07 05:46:27