在使用许多线程和进程时确保文件永远不会损坏的正确解决方案是什么。
线程版本,它关心打开错误。
lock = threading.RLock()
with lock:
try:
f = open(file, 'a')
try:
f.write('sth')
finally:
f.close() # try close in any circumstances if open passed
except:
pass # when open failed
对于进程我猜必须使用 multiprocessing.Lock
但是如果我想要 2 个进程,并且第一个进程拥有 2 个线程(每个线程都使用文件)
只有理论,但我想知道如何将同步与线程和进程结合起来。 线程是从进程“继承”它吗?所以只需要进程之间的同步?
和 2. 我不确定上面的代码是否需要嵌套尝试以防写入失败,并且我们想要关闭打开的文件(如果它在锁定释放后仍保持打开状态怎么办)
最佳答案
虽然这在 the docs 中并不完全清楚,多处理同步原语实际上也同步线程。
例如,如果您运行这段代码:
import multiprocessing
import sys
import threading
import time
lock = multiprocessing.Lock()
def f(i):
with lock:
for _ in range(10):
sys.stderr.write(i)
time.sleep(1)
t1 = threading.Thread(target=f, args=['1'])
t2 = threading.Thread(target=f, args=['2'])
t1.start()
t2.start()
t1.join()
t2.join()
...输出将始终是 1111111111222222222
或 22222222221111111111
,而不是两者的混合。
锁是在 Windows 上的 Win32 内核同步对象之上实现的,在支持它们的 POSIX 平台上是信号量,而在其他平台上根本没有实现。 (您可以使用 import multiprocessing.semaphore
对此进行测试,这将在其他平台上引发 ImportError
,如文档中所述。)
也就是说,拥有两级锁当然安全,只要您总是以正确的顺序使用它们——也就是说,永远不要抢threading.Lock
除非你能保证你的进程有 multiprocessing.Lock
。
如果您做得足够巧妙,它可以带来性能优势。 (Windows 和某些 POSIX 平台上的跨进程锁可能比进程内锁慢几个数量级。)
如果你只是以明显的方式去做(只在 with processlock:
block 中做 with threadlock:
),它显然不会提高性能,事实上会减慢速度(尽管很可能不足以衡量),并且不会增加任何直接好处。当然你的读者会知道你的代码是正确的,即使他们不知道 multiprocessing
锁在线程之间工作,并且在某些情况下调试进程内死锁比调试进程间死锁要容易得多......但是在大多数情况下,我认为这些都不足以成为额外复杂性的充分理由。
关于python - 使用线程和进程并发写入同一文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18412776/