【发布时间】:2011-02-13 23:43:46
【问题描述】:
另一个问题中的一些讨论鼓励我更好地理解多线程 Python 程序中需要锁定的情况。
根据this 关于 Python 中的线程的文章,我有几个可靠的、可测试的示例说明多个线程访问共享状态时可能发生的陷阱。本页提供的示例竞争条件涉及读取和操作存储在字典中的共享变量的线程之间的竞争。我认为在这里进行比赛的情况非常明显,幸运的是非常可测试。
但是,我无法通过诸如列表追加或变量增量之类的原子操作来引发竞争条件。该测试详尽地试图证明这样的比赛:
from threading import Thread, Lock
import operator
def contains_all_ints(l, n):
l.sort()
for i in xrange(0, n):
if l[i] != i:
return False
return True
def test(ntests):
results = []
threads = []
def lockless_append(i):
results.append(i)
for i in xrange(0, ntests):
threads.append(Thread(target=lockless_append, args=(i,)))
threads[i].start()
for i in xrange(0, ntests):
threads[i].join()
if len(results) != ntests or not contains_all_ints(results, ntests):
return False
else:
return True
for i in range(0,100):
if test(100000):
print "OK", i
else:
print "appending to a list without locks *is* unsafe"
exit()
我已经运行了上面的测试,没有失败(100x 100k 多线程追加)。谁能让它失败?是否有另一类对象可以通过原子的、增量的、线程修改来使其行为不端?
这些隐含的“原子”语义是否适用于 Python 中的其他操作?这是否与 GIL 直接相关?
【问题讨论】:
-
测试不是证明并发应用程序正确性的有效方法。对于任何特定的测试来说,以一种永远不会触发问题的可预测的方式交错执行是非常容易的,但是对代码的最微小的更改(即,将其扩展到现实世界的情况时)可能会立即显示出缺陷。并发软件的正确性应该被证明,而不是测试。
标签: python multithreading gil