python - 使用线程和进程并发写入同一文件

标签 python multithreading synchronization multiprocessing

在使用许多线程和进程时确保文件永远不会损坏的正确解决方案是什么。

线程版本,它关心打开错误。

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()

...输出将始终是 111111111122222222222222222221111111111,而不是两者的混合。

锁是在 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/

相关文章:

python - 我无法安装 pyopenjtalk "Getting requirements to build wheel did not run successfully."

python - 从图像( map )中提取多边形坐标

python - threading.Condition.wait() 未捕获 SIGTERM

java - 同步客户端-服务器游戏状态

ios - 如何在 objective-c 中为我的一系列任务创建队列

c - 没有锁的一插入多读列表安全吗?

python - 如何修复 anaconda 下损坏的 pip

python - pandas DataFrame 中的级别是什么?

c++ - 如何结合opencv和多线程?

java - 编写静态同步方法(等待线程的结果)