python编程语法基础笔记(4.15)(网络编程)
今天学习了 Python 中进程和线程的核心用法,涵盖进程创建、进程间通信、线程使用、线程数据共享等关键知识点.
一、进程相关
1. 自定义进程类(继承 Process)
通过继承multiprocessing.Process类自定义进程,需重写run()方法定义进程执行逻辑,初始化时要调用父类的__init__方法,支持传入自定义参数和 Process 类的原生参数.
class Study(Process):
def __init__(self,a,b,**kwargs):
super().__init__(**kwargs) # 继承Process的参数
self.a = a
self.b = b
def run(self): # 进程执行的核心逻辑
print(f'{self.a,self.b} - 进程ID:{os.getpid()}, 父进程ID:{os.getppid()}')
创建并启动进程:study = Study('hello','world',name='进程1') → study.start()。
2. 进程池(ProcessPoolExecutor)
使用concurrent.futures.ProcessPoolExecutor创建进程池,控制并行,避免资源耗尽,通过submit()提交任务,result()获取任务返回值,shutdown()等待所有任务完成。
executor = ProcessPoolExecutor(3) # 最多3个进程
f1 = executor.submit(study, 1) # 提交任务
print(f1.result()) # 获取返回值
executor.shutdown(wait=True) # 等待所有任务执行完毕
3. 进程间通信(IPC)
进程间相互隔离,需通过专用机制通信,核心有两种方式:
Queue 队列:先进先出(FIFO)结构
数据通过 “序列化→拷贝→共享内存→反序列化” 传递(非共享,是拷贝)。
支持put()(入队,满时阻塞)、get()(出队,空时阻塞),还有get_nowait()(非阻塞,空则抛异常)、empty()/full()/qsize()等方法。
q = Queue(2) # 容量为2的队列
p1 = Process(target=test1, args=(q,)) # 子进程1往队列放数据
p2 = Process(target=test2, args=(q,)) # 子进程2从队列取数据
Pipe 管道:类似 “水管”,可设置单向(duplex=False)/ 双向,通过send()发送数据、recv()接收数据。
con1, con2 = Pipe(duplex=False) # con1接收,con2发送
p1 = Process(target=test, args=(con1,))
p2 = Process(target=test2, args=(con2,))
二、线程相关
1. 线程创建与使用
通过threading.Thread创建线程,用法与 Process 类似,需指定target(执行函数)、args(参数)等,核心方法:
start():启动线程(交给操作系统调度);
join():等待线程执行完毕;
daemon=True:设置为守护线程(主进程 / 主线程结束,守护线程立即终止)。
lock = Lock()
p = Thread(target=study, args=(lock,), name='study')
p.daemon = True # 守护线程
p.start()
p.join() # 等待线程执行完
2. 线程数据共享与锁机制
线程共享进程的内存空间,全局变量可直接共享,但多线程修改共享数据会出现 “竞态条件”,需通过threading.Lock加锁/join()保证原子性:
acquire():获取锁(加锁);
release():释放锁(解锁);
也可使用with lock自动加锁 / 释放锁,更简洁。
num = 0 # 共享全局变量
def num1(lock):
global num
lock.acquire()
for i in range(10000000):
num += 1 # 加锁避免多线程同时修改
lock.release()
3. 进程与线程的基础标识
进程 ID:os.getpid()(当前进程)、os.getppid()(父进程);
线程 ID:threading.get_native_id()(当前线程编号)。
三、核心区别(进程 vs 线程)
进程是资源分配的最小单位,线程是 CPU 调度的最小单位;
进程间相互隔离,需 IPC 通信;线程共享进程资源,需锁保证数据安全;
进程创建 / 销毁开销大,线程开销小;
多进程可利用多核 CPU,多线程受 GIL 限制(Python 中同一时刻仅一个线程执行)。
四、注意事项
进程 / 线程创建时,start()才是真正向操作系统申请资源,仅创建对象不会启动;
队列put()/get()默认阻塞,可通过timeout/block=False设置非阻塞;
锁的使用要避免死锁,确保acquire()后必有release(),推荐with lock语法;
守护线程 / 进程需在start()前设置,主进程结束时,未设置守护的子进程会继续执行,守护的则终止。
更多推荐
所有评论(0)