Python并行执行 - threading.Lock不按意图工作

时间:2013-01-10 23:01:21

标签: python parallel-processing locking

我目前有一个全局Lock = threading.Lock(),并进行以下调用:

Parallel(n_jobs=2)(delayed(serialRemove)(dir,c,b,l,f) for f in os.listdir(dir))

使用jobLib。在serialRemove,我有

Lock.acquire()
print(f+' begin')
if h in hashes:
    try:
        os.remove(path)
        if l: print('Removing ' + path)
        removed += 1
    except os.error:
        print('Encountered error removing file') 
else:
    hashes.add(h)
print(f+' end')
Lock.release()

部分通话结果如下:
10.txt开始
11.txt开始
20.txt开始
如果我将代码包含在Lock中,我不明白如何有两个开始打印。是否有任何简单的方法来保护代码块,理想情况下我得到:
10.txt开始
10.txt结束
11.txt开始
11.txt结束
20.txt开始
20.txt结束

1 个答案:

答案 0 :(得分:4)

threading.Lock仅适用于同一进程的线程。

如果没有真正知道你在这里用于并行化的库,那么很难确定,但它几乎肯定会在不同的进程中执行任务。 (在同一进程中启动线程的任何东西,至少在CPython中,由于GIL,不会为CPU绑定代码获得任何有效的并行性。因此,他们都没有这样做。)

因此,如果您尝试使用来自其他进程的全局threading.Lock对象,那么您将在每个进程中获得完全独立的锁定。因此,锁定它没有任何好处。 (对于某些并行库 - 每个平台可能不同 - 你会得到一个错误。但是它没有办法可能做你想要的。)

大多数并行化库都有自己的锁类型,可以使用它们的多处理风格。如果是的话,请使用您的图书馆附带的那个。

如果没有,根据您的图书馆的工作方式,multiprocessing.Lock可能会有所帮助。

如果没有,您将必须使用例如锁定文件(可能与flock / lockf一起,或依赖Windows独占打开,或其他)明确实现某些内容。

另外,请注意,具有可以理解您的示例代码行[{joblib]的API的多个库中的至少一个是明确设计用于没有任何共享的任务,并且因此根本不应该使用锁。 (无论如何,它可能会与multiprocessing.Lock一起使用,但你真的不应该依赖它。)