MST

星途 面试题库

面试题:Python中线程替代方案之多进程相关问题

在Python中,多进程常常作为线程的一种替代方案。请简述多进程模块`multiprocessing`的基本使用方法,以及它相较于线程在数据共享和资源利用方面有哪些不同?
31.4万 热度难度
编程语言Python

知识考点

AI 面试

面试题答案

一键面试

multiprocessing基本使用方法

  1. 创建进程
    • 可以通过继承multiprocessing.Process类,并重写run方法来创建进程。
    import multiprocessing
    
    
    class MyProcess(multiprocessing.Process):
        def run(self):
            print(f"子进程 {self.name} 运行中")
    
    
    if __name__ == '__main__':
        p = MyProcess()
        p.start()
        p.join()
    
    • 也可以直接使用multiprocessing.Process类,传入要执行的函数。
    import multiprocessing
    
    
    def worker():
        print("子进程运行中")
    
    
    if __name__ == '__main__':
        p = multiprocessing.Process(target=worker)
        p.start()
        p.join()
    
  2. 传递参数:在使用Process类传入函数时,可以通过argskwargs传递参数。
    import multiprocessing
    
    
    def worker(num):
        print(f"子进程运行,参数为 {num}")
    
    
    if __name__ == '__main__':
        p = multiprocessing.Process(target=worker, args=(10,))
        p.start()
        p.join()
    
  3. 进程间通信
    • 队列(Queue):用于在进程间传递数据。
    import multiprocessing
    
    
    def producer(queue):
        for i in range(5):
            queue.put(i)
    
    
    def consumer(queue):
        while True:
            item = queue.get()
            if item is None:
                break
            print(f"消费: {item}")
    
    
    if __name__ == '__main__':
        q = multiprocessing.Queue()
        p1 = multiprocessing.Process(target=producer, args=(q,))
        p2 = multiprocessing.Process(target=consumer, args=(q,))
        p1.start()
        p2.start()
        p1.join()
        q.put(None)
        p2.join()
    
    • 管道(Pipe):用于创建双向或单向的通信通道。
    import multiprocessing
    
    
    def sender(conn):
        conn.send('Hello, receiver!')
        conn.close()
    
    
    def receiver(conn):
        msg = conn.recv()
        print(f"接收: {msg}")
        conn.close()
    
    
    if __name__ == '__main__':
        parent_conn, child_conn = multiprocessing.Pipe()
        p1 = multiprocessing.Process(target=sender, args=(child_conn,))
        p2 = multiprocessing.Process(target=receiver, args=(parent_conn,))
        p1.start()
        p2.start()
        p1.join()
        p2.join()
    

与线程在数据共享和资源利用方面的不同

  1. 数据共享
    • 线程:线程间共享全局变量,多个线程可以直接访问和修改相同的变量,这在提高数据访问效率的同时,容易引发资源竞争问题,需要使用锁(Lock)等机制来保证数据一致性。
    • 多进程:每个进程有自己独立的内存空间,默认情况下进程间数据不共享。如果需要共享数据,需要使用multiprocessing提供的ValueArray等共享内存对象,或者通过进程间通信(如队列、管道)来传递数据,相比线程数据共享的复杂性较低,但操作相对繁琐。
  2. 资源利用
    • 线程:所有线程共享进程的资源,如内存空间、文件描述符等,创建和销毁线程的开销相对较小。但是,由于全局解释器锁(GIL)的存在,在CPU密集型任务中,Python多线程无法充分利用多核CPU的优势,同一时间只有一个线程能执行Python字节码。
    • 多进程:每个进程拥有独立的资源,创建和销毁进程的开销相对较大。但是,多进程可以充分利用多核CPU的优势,适合CPU密集型任务,每个进程可以在不同的CPU核心上并行执行,提高整体的计算效率。