You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多进程日志写入冲突:如何跨进程共享单锁保证日志一致性?

问题解答

结论:可以通过多进程共享单个锁解决日志写入不一致的问题,但你当前使用的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 05:30:54