Python中的多进程与多线程详解

文章目录

  • 一、多进程(Multiprocessing)
  • 1.1 概念
  • 1.2 创建多进程的方式
  • 1.3 进程间通信(IPC)
  • 1.4 优点
  • 1.5 缺点
  • 二、多线程(Multithreading)
  • 2.1 概念
  • 2.2 创建多线程的方式
  • 2.3 线程同步机制
  • 2.4 优点
  • 2.5 缺点
  • 一、多进程(Multiprocessing)

    1.1 概念

  • 在Python中,多进程是指同时运行多个独立的进程。每个进程都有自己独立的内存空间,数据不共享(除非使用特定的进程间通信机制)。这意味着一个进程中的变量和状态不会直接影响其他进程,进程之间是相对独立的实体。
  • 1.2 创建多进程的方式

  • 使用 multiprocessing.Process
  • 示例:
    import multiprocessing
    
    def worker():
        print('This is a worker process')
    
    if __name__ == '__main__':
        p = multiprocessing.Process(target = worker)
        p.start()
        p.join()
    
  • 这里定义了一个函数 worker,然后通过创建 Process 类的实例,将 worker 函数作为目标函数。start 方法用于启动进程,join 方法用于等待进程结束。
  • 使用进程池(Pool
  • 示例:
    import multiprocessing
    
    def square(x):
        return x * x
    
    if __name__ == '__main__':
        with multiprocessing.Pool(processes = 4) as pool:
            results = pool.map(square, [1, 2, 3, 4, 5])
            print(results)
    
  • 进程池可以方便地管理多个进程。在这个例子中,定义了一个函数 square,然后使用进程池将该函数应用到一个列表中的每个元素上。
  • 1.3 进程间通信(IPC)

  • 队列(Queue
  • 示例:
    import multiprocessing
    
    def writer(q):
        for i in range(10):
            q.put(i)
    
    def reader(q):
        while True:
            try:
                item = q.get()
                print(item)
            except multiprocessing.Queue.Empty:
                break
    
    if __name__ == '__main__':
        q = multiprocessing.Queue()
        pw = multiprocessing.Process(target = writer, args=(q,))
        pr = multiprocessing.Process(target = reader, args=(q,))
        pw.start()
        pw.join()
        pr.start()
        pr.join()
    
  • 队列是一种常见的进程间通信方式。一个进程可以将数据放入队列,另一个进程可以从队列中取出数据。
  • 管道(Pipe
  • 示例:
    import multiprocessing
    
    def f(conn):
        conn.send([42, None, 'hello'])
        conn.close()
    
    if __name__ == '__main__':
        parent_conn, child_conn = multiprocessing.Pipe()
        p = multiprocessing.Process(target = f, args=(child_conn,))
        p.start()
        print(parent_conn.recv())
        p.join()
    
  • 管道提供了一种双向通信的方式,在父进程和子进程之间建立连接来传递数据。
  • 1.4 优点

  • 真正的并行执行:在多核CPU上,不同进程可以在不同的核心上同时运行,充分利用多核资源。
  • 进程间隔离性好:一个进程的崩溃通常不会影响其他进程,提高了系统的稳定性。
  • 1.5 缺点

  • 资源消耗较大:每个进程都有自己独立的内存空间等资源,相比于多线程,多进程占用更多的系统资源。
  • 进程间通信相对复杂:需要使用特定的进程间通信机制,如队列、管道等,不像多线程可以直接共享数据(虽然共享数据也有同步问题)。
  • 二、多线程(Multithreading)

    2.1 概念

  • 多线程是指在一个进程内部同时运行多个线程。线程是进程中的执行单元,同一个进程中的线程共享进程的内存空间,包括代码段、数据段等。这使得线程之间可以方便地共享数据,但也带来了数据同步的问题。
  • 2.2 创建多线程的方式

  • 使用 threading.Thread
  • 示例:
    import threading
    
    def worker():
        print('This is a worker thread')
    
    t = threading.Thread(target = worker)
    t.start()
    t.join()
    
  • 与多进程类似,这里定义了一个函数 worker,通过创建 Thread 类的实例,将 worker 函数作为目标函数,然后启动和等待线程。
  • 2.3 线程同步机制

  • 锁(Lock
  • 示例:
    import threading
    
    counter = 0
    lock = threading.Lock()
    
    def increment():
        global counter
        for _ in range(10000):
            lock.acquire()
            try:
                counter += 1
            finally:
                lock.release()
    
    t1 = threading.Thread(target = increment)
    t2 = threading.Thread(target = increment)
    t1.start()
    t2.start()
    t1.join()
    t2.join()
    print(counter)
    
  • 当多个线程访问共享资源(如这里的 counter)时,需要使用锁来保证数据的正确性。lock.acquire() 用于获取锁,lock.release() 用于释放锁。
  • 条件变量(Condition
  • 示例:
    import threading
    
    condition = threading.Condition()
    data = []
    
    def producer():
        global data
        with condition:
            for i in range(10):
                data.append(i)
                condition.notify()
    
    def consumer():
        global data
        with condition:
            while not data:
                condition.wait()
            item = data.pop()
            print(item)
    
    t1 = threading.Thread(target = producer)
    t2 = threading.Thread(target = consumer)
    t1.start()
    t2.start()
    t1.join()
    t2.join()
    
  • 条件变量用于在线程之间进行更复杂的同步操作,比如当某个条件满足时通知其他线程。
  • 2.4 优点

  • 轻量级:线程相比于进程占用更少的系统资源,创建和销毁线程的开销相对较小。
  • 方便共享数据:同一进程内的线程可以直接共享数据,无需复杂的通信机制(但需要注意同步问题)。
  • 2.5 缺点

  • 全局解释器锁(GIL):在CPython(Python的官方实现)中,存在全局解释器锁,这限制了多线程在多核CPU上的并行性。在同一时刻,只有一个线程可以执行Python字节码,所以多线程在计算密集型任务上可能无法充分利用多核优势。
  • 数据同步问题:由于线程共享数据,如果没有正确的同步机制,很容易导致数据不一致、竞争条件等问题。
  • 作者:Limiiiing

    物联沃分享整理
    物联沃-IOTWORD物联网 » Python中的多进程与多线程详解

    发表回复