文章目录
多进程
多进程使用流程
导入包
python
复制代码
import multiprocessing
Process进程类说明
text
复制代码
Process({group [, target [, name [, args [,kwargs]]]]})
group:指定进程组,目前只能使用None
target:执行的目标任务名
name:进程名字
args:以元组形式给执行任务传参
kwargs:以字典形式给执行任务传参
- Process创建实例对象的常用方法
- start():创建子进程
- join():等待子进程执行结束
- terminate():不管任务是否完成,立即终止子进程
- Process创建的实例对象的常用属性
- name:当前进程的别名,默认为Process-N,N为从1开始递增的整数
- 代码示例
python
复制代码
# *_*coding:utf-8 *_*
import multiprocessing
import time
def sing(msg):
for i in range(5):
print(f"{msg}")
time.sleep(1)
def dance(msg):
for i in range(5):
print(f'{msg}')
time.sleep(1)
if __name__ == '__main__':
# 单进程:需要至少10s钟完成
# sing("sing")
# dance("dance")
# 三个进程:1个主进程,2个子进程
# 创建子进程方式
# target为任务名,创建一个sing线程,通过元组方式传参
sing_obj = multiprocessing.Process(target=sing, args=("sing sing sing",))
# target为任务名,创建一个dance线程,通过字段方式传参
dance_obj = multiprocessing.Process(target=dance, kwargs={"msg": "dance dance dance"})
# 启动两个线程
sing_obj.start()
dance_obj.start()
获取进程编号
目的
- 获取进程编号的目的是验证主进程与子进程的关系,得知子进程是由哪个主进程创建出来的
常用操作
- 获取当前进程编号:
os.getpid()
- 回去当前父进程编号:
os.getppid
- 代码示例
python
复制代码
# *_*coding:utf-8 *_*
import multiprocessing
import os
def sing():
# 获取当前进程编号
print("sing当前进程编号: ", os.getpid())
# 获取当前进程
print("sing 当前进程: ", multiprocessing.current_process())
# 获取当前父进程编号
print("sing父进程编号: ", os.getppid())
if __name__ == '__main__':
# 获取主进程ID
print("main当前进程编号: ", os.getpid())
obj = multiprocessing.Process(target=sing)
obj.start()
获取进程名
python
复制代码
# *_*coding:utf-8 *_*
import multiprocessing
def sing():
# 获取当前进程名
print("sing 当前进程: ", multiprocessing.current_process())
if __name__ == '__main__':
# 获取主进程ID
obj = multiprocessing.Process(target=sing, name="test_dance")
obj.start()
进程注意点
进程之间不共享全局变量
- 进程是分配资源的最小单位,每个进程都会有自己的独立空间
- 创建子进程会对主进程资源进行拷贝,也就是说子进程是主进程的一个副本,之所以进程之间不共享全局变量,是因为操作的不是一个进程里面的全局变量,只不过不同进程里面的全局变量名字相同而已
- 代码示例
python
复制代码
# *_*coding:utf-8 *_*
import multiprocessing
import time
# 定义全局变量
g_num = 0
def my_read():
print("my_read:", g_num)
def my_write():
# 向全局变量中写数据
global g_num
g_num = 10
print("my_write:", g_num)
if __name__ == '__main__':
# 创建子进程
read_obj = multiprocessing.Process(target=my_read)
write_obj = multiprocessing.Process(target=my_write)
# 开启子进程
write_obj.start()
# 保证全局变量数据被写入
time.sleep(1)
read_obj.start()
主进程会等待子进程结束之后再结束
python
复制代码
# *_*coding:utf-8 *_*
import multiprocessing
import time
def func():
for i in range(5):
time.sleep(0.3)
print("func()")
if __name__ == '__main__':
obj = multiprocessing.Process(target=func)
obj.start()
print("main")
exit(0)
设置守护主进程
- 设置守护主进程的目的是,主进程退出子进程销毁,不让主进程等待子进程去执行
- 设置守护主进程方式:子进程对象.daemon=true
- 销毁子进程方式:子进程对象.terminate()
- 注意:需要在子进程start之前设置
多线程
threading模块
- Python的多线程可以通过threading模块来实现
- 语法
python
复制代码
import threading
thread_obj = threading.Thread([group[, target[, name[, args[, kwargs]]]]])
group:预留参数,暂未使用
target:执行的目标任务名
args:以元组的方式给执行任务传参
kwargs:以字典的方式给执行任务传参
name:线程名,一般不设置
# 启动线程
thread_obj.start()
python
复制代码
# *_*coding:utf-8 *_*
import time
import threading
def sing(msg):
while True:
print(f"{msg}")
time.sleep(1)
def dance(msg):
while True:
print(f'{msg}')
time.sleep(1)
if __name__ == '__main__':
# 创建一个sing线程,通过元组方式传参
sing_thread_obj = threading.Thread(target=sing, args=("sing sing sing",))
# 创建一个dance线程,通过字段方式传参
dance_thread_obj = threading.Thread(target=dance, kwargs={"msg": "dance dance dance"})
# 启动两个线程
sing_thread_obj.start()
dance_thread_obj.start()
线程注意点
线程之间执行是无序的
python
复制代码
# *_*coding:utf-8 *_*
import threading
import time
def func():
# sleep的时候CPU是空闲的,所有创建出来的线程都在等待CPU的执行
time.sleep(0.3)
# 实际执行线程位置
print(threading.current_thread())
if __name__ == '__main__':
for _ in range(5):
# 创建线程位置
my_func = threading.Thread(target=func)
my_func.start()
主线程会等待所有的子线程执行结束在结束
python
复制代码
# *_*coding:utf-8 *_*
import threading
import time
def func():
for _ in range(5):
time.sleep(0.2)
print("func")
if __name__ == '__main__':
obj = threading.Thread(target=func)
obj.start()
time.sleep(0.5)
print("main over")
- 设置守护线程
- 设置方式
- 方式一:threading.Thread(target=方法名, daemon=True)
- 方式二:线程对象.setDaemon(True)
- 代码示例
python
复制代码
# *_*coding:utf-8 *_*
import threading
import time
def func():
for _ in range(5):
time.sleep(0.2)
print("func")
if __name__ == '__main__':
# # 不设置守护线程方式
# obj = threading.Thread(target=func)
# # 设置守护线程方式一
# obj = threading.Thread(target=func, daemon=True)
obj = threading.Thread(target=func)
# 设置守护线程方式二
obj.setDaemon(True)
obj.start()
time.sleep(0.5)
print("main over")
线程之间共享全局变量
python
复制代码
# *_*coding:utf-8 *_*
import threading
import time
g_num = []
def my_read():
global g_num
print("my_read: ", g_num)
def my_write():
global g_num
for i in range(5):
g_num.append(i)
print("my_write: ", g_num)
if __name__ == '__main__':
print("main start: ", g_num)
write_obj = threading.Thread(target=my_write)
read_obj = threading.Thread(target=my_read)
write_obj.start()
# 确保write先执行
time.sleep(0.1)
read_obj.start()
print("main finish: ", g_num)
线程之间共享全局变量数据出现错误问题
python
复制代码
# *_*coding:utf-8 *_*
import threading
g_num = 0
def func1():
global g_num
for _ in range(1000000):
g_num += 1
print("func1: ", g_num)
def func2():
global g_num
for _ in range(1000000):
g_num += 1
print("func2: ", g_num)
if __name__ == '__main__':
obj1 = threading.Thread(target=func1)
obj2 = threading.Thread(target=func2)
obj1.start()
obj2.start()
print(g_num)
多线程共享全局变量问题
线程等待
- 语法:子线程.join()
- 功能:让主线程等待当前子线程执行完毕在继续向下执行
- 代码示例
python
复制代码
# *_*coding:utf-8 *_*
import threading
g_num = 0
def func1():
global g_num
for _ in range(1000000):
g_num += 1
print("func1: ", g_num)
def func2():
global g_num
for _ in range(1000000):
g_num += 1
print("func2: ", g_num)
if __name__ == '__main__':
obj1 = threading.Thread(target=func1)
obj2 = threading.Thread(target=func2)
obj1.start()
obj1.join()
obj2.start()
obj2.join()
print(g_num)
互斥锁
- 对共享数据进行锁定,保证同一时刻只能有一个线程去操作
- 基本使用语法
python
复制代码
# 创建锁
mutex = threading.Lock()
# 上锁
mutex.acquire()
# 释放锁
mutex.release()
python
复制代码
# *_*coding:utf-8 *_*
import threading
g_num = 0
# 创建锁
mutex = threading.Lock()
def func1():
global g_num
# 加锁
mutex.acquire()
for _ in range(1000000):
g_num += 1
# 释放锁
mutex.release()
print("func1: ", g_num)
def func2():
global g_num
# 加锁
mutex.acquire()
for _ in range(1000000):
g_num += 1
# 释放锁
mutex.release()
print("func2: ", g_num)
if __name__ == '__main__':
obj1 = threading.Thread(target=func1)
obj2 = threading.Thread(target=func2)
obj1.start()
obj2.start()