上篇文章主要了解python的线程,如何创建线程,如何通过线程实现生产者-消费者模式以及线程池的使用等等,接下来这篇文章讲解python的进程,有问题欢迎一起探讨。
在 python 中,进程是操作系统分配的独立执行单元,它包含程序代码、数据以及一系列运行时资源,如内存、文件描述符等。进程是操作系统进行任务调度和资源管理的基本单位。python 提供了多种方法来创建和管理进程,通常通过 multiprocessing 模块来实现多进程操作。
进程是操作系统中正在执行的程序实例。每个进程都有自己的内存空间、全局变量以及系统资源。进程之间是独立的,一个进程的崩溃不会影响其他进程。
特点:
由于 python 的全局解释器锁:GIL,多线程在 python 中无法实现真正的并行,尤其是 CPU 密集型任务。因此,对于这种任务,通常会使用多进程方式代替多线程。python 提供了 multiprocessing 模块来轻松创建和管理多个进程。
multiprocessing 模块
该模块允许通过创建子进程的方式并行地执行任务。这个模块提供了与 threading 模块类似的接口,但进程之间的内存是独立的,需要使用进程间通信IPC来进行数据交换。
示例:
import multiprocessing
import os
def worker():
print(f"Worker Process ID: {os.getpid()}")
if __name__ == "__main__":
# 创建子进程
process = multiprocessing.Process(target=worker)
process.start()
process.join() # 等待子进程完成在该例子中,worker 函数在子进程中运行,multiprocessing.Process 用来创建和管理子进程。
进程常用功能主要有以下几种:
Process 类:用于创建一个新进程,执行指定的目标函数。
Pool 类:用于管理进程池,以便在多个进程之间并行执行任务。
Queue、Pipe、Value、Array 等方式实现进程间的数据共享和通信。
Lock、Event、Semaphore 等,用于确保进程之间的同步,避免资源竞争问题。
多进程常用于以下场景:
进程是操作系统管理资源的基本单位,每个进程都有独立的内存空间和资源。multiprocessing 模块提供了易于使用的接口,方便创建和管理多进程。进程间通信可以通过队列、管道等方式来实现,但进程之间的资源是独立的。多进程尤其适用于 CPU 密集型任务,能够提升性能。
多进程通信是指不同进程之间交换数据和信息的方式。由于进程有独立的内存空间,它们之间的数据不能直接共享,因此需要使用特定的通信机制来进行数据交换。python 的 multiprocessing 模块提供了多种进程间通信的方式,通过五个方面介绍多进程通信的机制;
Queue 是一种线程安全的队列,用于在进程之间传递数据。它支持先进先出操作,适合用于进程间的消息传递和任务分配。
特点:
Queue 实现了线程安全,因此可以被多个进程同时访问而不需要额外的锁。
put()、get()、empty() 等方法进行数据操作。
示例:
from multiprocessing import Process, Queue
def worker(q):
q.put("Hello from worker")
if __name__ == "__main__":
q = Queue()
p = Process(target=worker, args=(q,))
p.start()
print(q.get()) # 从队列中获取数据
p.join()Pipe 提供了一对连接的管道,允许两个进程进行双向通信。每个管道有两个端点,一个用于发送数据,另一个用于接收数据。
特点:
Pipe 进行双向数据传输,但需要在两个进程中分别使用 conn1.send() 和 conn2.recv() 进行通信。
Queue 更轻量,适合用于简单的进程间通信。
示例:
from multiprocessing import Process, Pipe
def worker(conn):
conn.send("Hello from worker")
conn.close()
if __name__ == "__main__":
parent_conn, child_conn = Pipe()
p = Process(target=worker, args=(child_conn,))
p.start()
print(parent_conn.recv()) # 从管道中接收数据
p.join()Value 和 Array 是用于在进程之间共享简单数据类型,如整数、浮点数和数组的机制。这些对象被存储在共享内存中,因此可以被多个进程直接访问。
特点:
Lock来进行同步。
示例:
from multiprocessing import Process, Value, Array, Lock
def worker(val, arr, lock):
with lock:
val.value += 1
for i in range(len(arr)):
arr[i] += 1
if __name__ == "__main__":
lock = Lock()
val = Value('i', 0)
arr = Array('i', range(10))
p = Process(target=worker, args=(val, arr, lock))
p.start()
p.join()
print(val.value) # 打印共享的整数值
print(arr[:]) # 打印共享的数组Lock:用于进程间的互斥访问,防止多个进程同时访问共享资源而导致数据竞争。
Event:用于进程间的同步,通过设置和清除事件来协调进程之间的活动。
Semaphore:用于控制对共享资源的访问,允许一定数量的进程同时访问资源。
Condition:提供更复杂的同步机制,允许进程在某些条件满足时进行通信和同步。
示例:
from multiprocessing import Process, Lock, Value
def worker(val, lock):
with lock:
val.value += 1
if __name__ == "__main__":
lock = Lock()
val = Value('i', 0)
processes = [Process(target=worker, args=(val, lock)) for _ in range(10)]
for p in processes:
p.start()
for p in processes:
p.join()
print(val.value) # 打印最终的共享整数值对于更复杂的数据共享场景,可以使用 multiprocessing.Manager 提供的 Manager 对象来创建和管理共享的命名空间和数据结构,如字典、列表等。
示例:
from multiprocessing import Process, Manager
def worker(shared_dict):
shared_dict['key'] = 'value'
if __name__ == "__main__":
manager = Manager()
shared_dict = manager.dict()
p = Process(target=worker, args=(shared_dict,))
p.start()
p.join()
print(shared_dict) # 打印共享的字典内容python的进程池multiprocessing.Pool是 multiprocessing 模块提供的一种高级并行处理方式,用于同时执行多个进程,从而充分利用多核CPU资源。在许多需要并行执行任务的场景下,进程池可以大大简化并行代码的编写,并提高程序的运行效率。
进程池提供了一种机制,可以一次性创建多个进程并将其放入池中,方便在需要时复用这些进程。这样避免了频繁创建和销毁进程的开销。在处理大量任务时,将任务分配给多个进程池中的进程并行处理,可以显著加速任务执行。
(1)Pool(): 创建进程池对象。
Pool([processes]):processes 是可选参数,指定进程池中并行执行的进程数量。如果不指定,默认使用系统的CPU核心数量。(2)apply(): 同步地将任务提交给进程池中的某个进程执行,直到任务完成后才返回结果。
apply(func, args=()):执行一个函数,并传递参数。该方法会阻塞主进程,直到任务完成并返回结果。(3)apply_async(): 异步地将任务提交给进程池中的某个进程执行,不会阻塞主进程。
apply_async(func, args=(), callback=None):异步调用某个函数,可以通过 callback 参数获取任务完成后的结果。(4)map(): 同步地将可迭代对象的每个元素分配给进程池中的进程执行指定函数,类似于 map() 函数,但支持并行。
map(func, iterable):阻塞主进程,直到所有任务完成后返回结果。(5)map_async(): 异步地将可迭代对象的每个元素分配给进程池中的进程执行指定函数,不会阻塞主进程。
map_async(func, iterable):和 map() 类似,但不阻塞主进程。(6)close(): 关闭进程池,防止新的任务提交。已经提交的任务会继续执行,直到完成。
(7)join(): 等待所有进程池中的进程执行完毕,通常在调用 close() 之后使用。
(8)terminate(): 强行终止所有正在执行的进程,不等待任务完成。
示例:
import multiprocessing
import time
def worker_function(x):
return x * x
if __name__ == "__main__":
# 创建一个进程池,指定最大并发进程数为4
pool = multiprocessing.Pool(processes=4)
# 使用map方法同步执行任务
results = pool.map(worker_function, range(10))
print("同步执行结果:", results)
# 异步执行任务
async_result = pool.apply_async(worker_function, args=(5,))
print("异步执行结果:", async_result.get()) # 获取异步执行的结果
# 关闭进程池并等待所有进程结束
pool.close()
pool.join()生产者-消费者模式是一种常见的并发设计模式,用于解决不同生产者线程/进程和消费者线程/进程之间的协作问题。其核心思想是通过某种中间数据结构来解耦生产者和消费者,使它们之间的执行流程独立。生产者产生数据,消费者消耗数据,而队列负责在两者之间传递数据。
在生产者-消费者模式中:
python标准库中的 multiprocessing 模块提供了 Queue 对象,用来在多个进程之间传递数据,非常适合实现生产者-消费者模式。queue.Queue 对象用于多线程场景,而 multiprocessing.Queue 适用于多进程场景。
Queue 提供的同步机制,自动处理生产者和消费者之间的资源争用问题,避免死锁或数据竞争。
以下示例展示了如何使用 multiprocessing 模块中的 Process 和 Queue 实现生产者-消费者模式
import multiprocessing
import time
import random
# 生产者函数
def producer(queue, items):
for item in items:
print(f"生产者正在生产: {item}")
queue.put(item) # 将生产的数据放入队列
time.sleep(random.uniform(0.1, 0.5)) # 模拟生产时间
queue.put(None) # 用于结束信号,通知消费者结束
# 消费者函数
def consumer(queue):
while True:
item = queue.get() # 从队列中取数据
if item is None: # 如果取到的是结束信号,退出循环
break
print(f"消费者正在消费: {item}")
time.sleep(random.uniform(0.1, 0.5)) # 模拟消费时间
if __name__ == "__main__":
# 创建一个队列,用于生产者和消费者之间的通信
queue = multiprocessing.Queue()
# 定义要生产的项目列表
items_to_produce = ['item1', 'item2', 'item3', 'item4', 'item5']
# 创建生产者进程
producer_process = multiprocessing.Process(target=producer, args=(queue, items_to_produce))
# 创建消费者进程
consumer_process = multiprocessing.Process(target=consumer, args=(queue,))
# 启动生产者和消费者进程
producer_process.start()
consumer_process.start()
# 等待生产者进程结束
producer_process.join()
# 等待消费者进程结束
consumer_process.join()
print("生产与消费过程结束。")代码运行逻辑:
item1 到 item5),并将其逐个放入共享队列中。生产完毕后,生产者放入一个 None 作为结束信号,告诉消费者任务已经完成。
None 结束信号为止。每次从队列中取出数据后进行处理。
multiprocessing.Queue 在生产者和消费者之间共享数据,确保数据能够安全地在多个进程之间传递。它内部会处理进程间的锁和同步问题,避免数据竞争。
生产者-消费者模式在Python中是一种非常实用的并发编程模式,适用于多线程或多进程的任务处理。通过队列来管理生产者和消费者之间的数据流动,可以实现任务的解耦和高效并发。这种模式广泛应用于各种需要异步任务处理的场景中,如消息处理系统、日志记录系统和大规模并发数据处理系统。
Python 的进程(Process)和线程(Thread)是两种用于并发执行任务的机制,它们各有不同的特性和适用场景。下面从多个方面详细对比 Python 中的进程和线程。
进程
线程
进程:
from multiprocessing import Process
def worker():
print("Worker process")
if __name__ == "__main__":
p = Process(target=worker)
p.start()
p.join()线程:
import threading
def worker():
print("Worker thread")
if __name__ == "__main__":
t = threading.Thread(target=worker)
t.start()
t.join()这篇文章讲的是python的进程,包括进程间通信、进程池、进程的生产者消费者模式以及进程和线程的对比,进程间的资源是互相隔离的,需要使用Queue等对象才能进行通信,进程适用于运行CPU 密集型任务以及任务型隔离,下篇文章接着讲python的协程,可以期待一下!