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

一、多进程(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字节码,所以多线程在计算密集型任务上可能无法充分利用多核优势。
  • 数据同步问题:由于线程共享数据,如果没有正确的同步机制,很容易导致数据不一致、竞争条件等问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Limiiiing

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值