面试题答案
一键面试多线程场景
- 使用方式:在Python多线程中,
threading
模块提供了锁(Lock
)机制,文件锁可通过fcntl
模块实现。以fcntl.flock
函数为例,它可以对文件描述符加锁。 - 注意事项:由于GIL(全局解释器锁)的存在,Python多线程在CPU密集型任务上无法利用多核优势,但在I/O密集型任务中,文件锁能有效防止多线程同时读写文件造成的数据不一致。需要注意及时释放锁,避免死锁。
实现思路:
- 打开文件获取文件描述符。
- 在读写操作前获取文件锁。
- 完成操作后释放文件锁。
关键代码片段:
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,但进程间通信和资源管理比多线程复杂。要确保每个进程正确获取和释放锁,避免锁争用和死锁。
实现思路:
- 创建进程锁对象。
- 在每个进程中,打开文件获取文件描述符。
- 在读写操作前通过进程锁获取文件锁。
- 完成操作后释放文件锁。
关键代码片段:
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系统中可不写,但建议保留以增强代码的可移植性。