面试题答案
一键面试可能遇到的问题
- 数据竞争:多个线程或进程同时访问和修改函数返回的共享数据,导致数据不一致。例如,多个线程对一个共享的列表进行添加元素操作,由于执行顺序不确定,可能会出现元素丢失或重复添加的情况。
- 资源共享:如果函数返回的多个值依赖于共享资源(如文件、数据库连接等),多个线程或进程同时访问可能导致资源冲突。例如,多个进程同时尝试写入同一个文件,可能会导致文件内容混乱。
避免问题的设计方法
- 线程安全的数据结构:使用Python提供的线程安全数据结构,如
queue.Queue
。它内部实现了锁机制,能够安全地在多线程间传递数据。 - 锁机制:对于共享资源,使用锁(
threading.Lock
或multiprocessing.Lock
)来确保同一时间只有一个线程或进程可以访问和修改共享数据。 - 进程间通信(IPC):在多进程场景中,使用合适的IPC机制,如
multiprocessing.Queue
、multiprocessing.Pipe
等,来传递函数返回的多个值,避免直接共享内存带来的问题。
代码示例
- 多线程示例
import threading
import queue
def worker(q):
result1 = "result1 from worker"
result2 = "result2 from worker"
q.put((result1, result2))
if __name__ == "__main__":
q = queue.Queue()
threads = []
for _ in range(5):
t = threading.Thread(target=worker, args=(q,))
threads.append(t)
t.start()
for t in threads:
t.join()
while not q.empty():
result1, result2 = q.get()
print(f"Received: {result1}, {result2}")
在这个多线程示例中,使用queue.Queue
来安全地传递函数返回的多个值,避免了数据竞争。
- 多进程示例
import multiprocessing
def worker(q):
result1 = "result1 from worker"
result2 = "result2 from worker"
q.put((result1, result2))
if __name__ == "__main__":
q = multiprocessing.Queue()
processes = []
for _ in range(5):
p = multiprocessing.Process(target=worker, args=(q,))
processes.append(p)
p.start()
for p in processes:
p.join()
while not q.empty():
result1, result2 = q.get()
print(f"Received: {result1}, {result2}")
在多进程示例中,使用multiprocessing.Queue
来实现进程间安全的数据传递,避免了资源共享和数据竞争问题。