多进程日志写入冲突:如何跨进程共享单锁保证日志一致性?
问题解答
结论:可以通过多进程共享单个锁解决日志写入不一致的问题,但你当前使用的threading.Lock无法满足需求,必须改用跨进程有效的锁机制。
为什么当前锁无效?
你现在在Log_writer1.py和Log_writer2.py里各自创建了threading.Lock实例,这种锁是线程级别的——它只能约束同一进程内的线程,对不同进程完全不起作用。两个cron任务是独立的进程,它们的锁相互隔离,所以依然会同时写入日志文件,导致数据错乱、内容丢失。
可行的跨进程锁方案
有两种常用的跨进程锁实现方式:
1. 使用文件锁(最适合cron独立进程场景)
利用操作系统的文件锁机制(Linux/macOS用fcntl,Windows用msvcrt),通过锁定一个专门的锁文件,让所有写入进程在操作日志前先获取锁,确保同一时间只有一个进程写入。这种方式无需进程间共享内存,适配cron独立启动进程的场景。
2. 使用multiprocessing.Lock(适用于父进程管理子进程的场景)
如果两个进程由同一个父进程启动,可以通过共享multiprocessing.Lock实例同步,但cron独立启动的进程需要借助共享内存或文件传递锁句柄,实现复杂度更高。
修改后的代码示例
以下是基于文件锁的实现,适配你的cron任务场景:
1. 更新test_cifs_log_writer.py
import time import fcntl # Linux/macOS环境用这个,Windows替换为import msvcrt def log_event(level, msg, job_log_file, lock_file_path): # 打开锁文件并获取排他锁,阻塞等待直到拿到锁 with open(lock_file_path, 'w') as lock_file: fcntl.flock(lock_file, fcntl.LOCK_EX) # Windows替换为msvcrt.locking(lock_file.fileno(), msvcrt.LK_LOCK, 1) # 将文件打开操作放在锁内,减少IO次数并避免重复打开的冲突 with open(job_log_file, 'a') as wr_log: for i in range(50): log_line = f"{time.ctime()} - {level.upper()} - {msg}\n" print(f'Now printing message : {msg}') wr_log.write(log_line) # 锁会在with块结束时自动释放
2. 修改Log_writer1.py
from threading import Thread from test_cifs_log_writer import log_event # 所有进程共用同一个锁文件路径 LOCK_FILE = "./log_lock.lock" t1 = Thread(target=log_event, args=('info', 'Thread 1 : msg', 'test_log_file.txt', LOCK_FILE)) t2 = Thread(target=log_event, args=('info', 'Thread 2 : msg', 'test_log_file.txt', LOCK_FILE)) lst = [t1, t2] for thr in lst: thr.start() for thr in lst: thr.join()
3. 修改Log_writer2.py
from threading import Thread from test_cifs_log_writer import log_event # 和Log_writer1使用完全相同的锁文件路径 LOCK_FILE = "./log_lock.lock" t1 = Thread(target=log_event, args=('info', 'Thread 3 : msg', 'test_log_file.txt', LOCK_FILE)) t2 = Thread(target=log_event, args=('info', 'Thread 4 : msg', 'test_log_file.txt', LOCK_FILE)) lst = [t1, t2] for thr in lst: thr.start() for thr in lst: thr.join()
额外优化点
- 把日志文件的打开操作移到锁内部,避免循环中反复打开关闭文件,既提升效率又减少潜在IO冲突。
- 用f-string替代字符串拼接,代码更简洁易读。
内容的提问来源于stack exchange,提问作者Raj Raj
相关产品推荐
相关产品推荐

