我有以下Python代码:
pool = ThreadPool(32)
l = defaultdict(lambda: 0)
def func(e):
if "$" in e:
l["included"] += 1
else:
l["not_included"] += 1
with open(file_name) as file:
data = file_name.readlines()
pool.map(func, data)
with open("output/logs.txt") as file:
file.write(l)
从本质上讲,它正在文件中寻找包含字符“ $”的行。但是,每次执行代码时,该输出文件都是不同的,这意味着要附加的列表l
是不同的。可能是什么原因造成的?
令人困惑的部分是,所产生的defaultdict l
与每次执行都不同。有时l = {"included": 772, "not_included": 9992}
,有时l = {"included": 878, "not_included": 6907}
等
答案 0 :(得分:0)
func
的每个操作都花费不同的时间。考虑:
>>> from multiprocessing.dummy import Pool as ThreadPool
>>> from random import randrange
>>> min_time = 0
>>> max_time = 4
>>> import time
>>> pool = ThreadPool(4)
>>> lst = []
>>> def func(e):
... time.sleep(randrange(min_time, max_time))
... lst.append(e ** 2)
...
>>> data = list(range(20))
>>> pool.map(func, data)
>>> lst
[0, 4, 1, 36, 9, 16, 100, 121, 64, 81, 144, 49, 25, 169, 256, 289, 196, 225, 324, 361]
每个线程调用func
,但是花费的时间不同。由于有多个线程同时运行,因此不能保证以任何顺序追加线程。
也许第一个线程从输入0开始,但是需要2秒钟,但是第二个线程从1开始,并且花费不到一秒钟。在这种情况下,将首先附加以1调用func
的结果。
编辑:我假设文件的长度是相同的,而顺序是不同的。
答案 1 :(得分:0)
因为map()
从线程返回值,所以我用它返回True或False,然后在主线程中计数它们。这样,线程就不会尝试使用通常会造成问题的同一l
。
from multiprocessing.pool import ThreadPool
pool = ThreadPool(32)
def func(e):
return "$" in e
data = ['$','$','x','$','$','x','$','$','x','x','$','x','x']
results = pool.map(func, data)
print(results)
l = dict()
l["included"] = results.count(True)
l["not included"] = results.count(False)
print(l)
结果
[True, True, False, True, True, False, True, True, False, False, True, False, False]
{'included': 7, 'not included': 6}
问题是当一个线程正在更改值但不阻止对变量的访问时,因此同时另一个线程获得旧值而不是新值,并且它修改了该旧值并将其放回变量,从而产生错误结果。线程必须使用一些Lock或Semaphor来阻止对变量的访问。