MST

星途 面试题库

面试题:Python文件锁机制在多线程与多进程场景下的差异

在Python中,分别阐述文件锁机制在多线程和多进程场景下的使用方式和注意事项。假设你有一个需要多个线程或进程共同读写的文件,如何通过文件锁来保证数据的一致性和安全性?请给出具体的实现思路和关键代码片段。
19.3万 热度难度
编程语言Python

知识考点

AI 面试

面试题答案

一键面试

多线程场景

  • 使用方式:在Python多线程中,threading模块提供了锁(Lock)机制,文件锁可通过fcntl模块实现。以fcntl.flock函数为例,它可以对文件描述符加锁。
  • 注意事项:由于GIL(全局解释器锁)的存在,Python多线程在CPU密集型任务上无法利用多核优势,但在I/O密集型任务中,文件锁能有效防止多线程同时读写文件造成的数据不一致。需要注意及时释放锁,避免死锁。

实现思路

  1. 打开文件获取文件描述符。
  2. 在读写操作前获取文件锁。
  3. 完成操作后释放文件锁。

关键代码片段

import fcntl
import threading

def read_write_file():
    with open('test.txt', 'a+') as file:
        fd = file.fileno()
        fcntl.flock(fd, fcntl.LOCK_EX)  # 获取排他锁
        try:
            file.seek(0)
            data = file.read()
            print(f"Read data: {data}")
            file.write('new content\n')
        finally:
            fcntl.flock(fd, fcntl.LOCK_UN)  # 释放锁

threads = []
for _ in range(3):
    thread = threading.Thread(target=read_write_file)
    threads.append(thread)
    thread.start()

for thread in threads:
    thread.join()

多进程场景

  • 使用方式:在多进程场景下,multiprocessing模块提供了锁(Lock)。同样可以结合fcntl模块的文件锁机制,不同进程通过获取文件锁来保证对文件的安全访问。
  • 注意事项:多进程没有GIL限制,能更好利用多核CPU,但进程间通信和资源管理比多线程复杂。要确保每个进程正确获取和释放锁,避免锁争用和死锁。

实现思路

  1. 创建进程锁对象。
  2. 在每个进程中,打开文件获取文件描述符。
  3. 在读写操作前通过进程锁获取文件锁。
  4. 完成操作后释放文件锁。

关键代码片段

import fcntl
import multiprocessing


def read_write_file(lock):
    with open('test.txt', 'a+') as file:
        fd = file.fileno()
        lock.acquire()
        try:
            fcntl.flock(fd, fcntl.LOCK_EX)
            file.seek(0)
            data = file.read()
            print(f"Read data: {data}")
            file.write('new content from process\n')
        finally:
            fcntl.flock(fd, fcntl.LOCK_UN)
            lock.release()


if __name__ == '__main__':
    lock = multiprocessing.Lock()
    processes = []
    for _ in range(3):
        process = multiprocessing.Process(target=read_write_file, args=(lock,))
        processes.append(process)
        process.start()

    for process in processes:
        process.join()

在多进程代码中,if __name__ == '__main__': 是Windows系统下运行多进程的必要条件,在Unix - like系统中可不写,但建议保留以增强代码的可移植性。