多任务:在同一时间内执行多个任务
多任务的目的:多任务的最大好处是充分利用CPU资源,提高程序的执行效率
并发
:在一段时间内交替执行多个任务
并行
:在同一时刻同时执行多个任务
进程:运行中的程序,分配资源的最小单位
线程:使用资源的最小单位
进程和线程的关系:一个程序运行后至少有一个进程,每个进程默认有一个线程
导入进程模块(multiprocessing)
import multiprocessing
创建子进程对象
sub_process = multiprocessing.Process(group=None, target=None, name=None, args, kwargs)
# 其中:args 方式传参应注意参数顺序一致,kwargs 传参应注意字典的 key 与参数名一致
启动子进程
sub_process.start() #启动子进程
sub_process.join() # 进程等待
sub_process.terminate() # 终止子进程
multiprocessing.current_process() #查看当前进程
os.getpid() # 查看进程编号
os.getppid() # 查看父进程编号
os.kill(进程编号,9) # 根据进程编号强制杀死进程
print(a, b, c) # 可以直接打印变量 a b c
# 进程的运行是无序的,不依赖代码的先后顺序
实例:
# 单进程
import time
def dance():
for i in range(5):
time.sleep(1)
print("DANCE", i)
def sing():
for i in range(5):
time.sleep(1)
print("SING", i)
if __name__ == '__main__':
dance()
sing()
[运行结果]
[Done] exited with code=0 in 10.052 seconds
# 多进程
import time
# 导入进程模块
import multiprocessing
def dance():
for i in range(5):
time.sleep(1)
print("DANCE", i)
def sing():
for i in range(5):
time.sleep(1)
print("SING", i)
if __name__ == '__main__':
# 创建子进程
my_dance = multiprocessing.Process(target=dance)
my_sing = multiprocessing.Process(target=sing)
# 启动子进程
my_dance.start()
my_sing.start()
[运行结果]
[Done] exited with code=0 in 5.095 seconds
目的: 知道子进程是由哪个主进程创建的(子进程需要主进程回收资源)
os.getpid()
: 表示获取当前进程编号
os.getppid()
: 表示获取当前父进程编号
进程起名字
my_dance = multiprocessing.Process(target=dance, name="my_ProcessName")
获取进程的名字
multiprocessing.current_process()
# 运行结果
带有参数的函数:
args: 元组!!!(单个元素的元组有 , )
my_dance = multiprocessing.Process(target=dance, args=(5,))
kwargs: 字典!!!(key值要和函数中的形参完全重名)
my_dance = multiprocessing.Process(target=dance, kwargs={"count": 5})
进程之间不共享全局变量,是因为操作的不是同一个进程里面的全局变量,只不过不同进程里面的全局变量名字相同而已
import multiprocessing
import time
# 全局变量列表
g_num = []
def my_write(): # 向全局变量g_num里写入数据
global g_num
for i in range(5):
g_num.append(i)
print("my_write:", g_num)
def my_read(): #读取全局变量g_num的值
global g_num
print("my_read:", g_num)
if __name__ == '__main__':
sub_write = multiprocessing.Process(target=my_write)
sub_read = multiprocessing.Process(target=my_read)
sub_write.start()
time.sleep(1) # 保证数据写入g_num中
sub_read.start()
[运行结果]
my_write: [0, 1, 2, 3, 4]
my_read: []
为了保证子进程能够正常的运行,主进程会等所有的子进程执行完成以后再销毁
设置守护主进程或销毁主进程的目的是主进程退出子进程销毁,不让主进程再等待子进程去执行
实例
import time
# 导入线程模块
import threading
def dance():
for i in range(5):
time.sleep(1)
print("DANCE", i)
def sing():
for i in range(5):
time.sleep(1)
print("SING", i)
if __name__ == '__main__':
# 创建子进程
my_dance = threading.Thread(target=dance)
my_sing = threading.Thread(target=sing)
# 启动子进程
my_dance.start()
my_sing.start()
[运行结果]
[Done] exited with code=0 in 5.042 seconds
主线程会等待子线程的结束而结束
设置守护主线程的两种方式:
好处是可以对全局变量的数据进行共享
但是可能会导致数据出现错误问题
import threading
import time
g_num = []
def my_write():
global g_num
for i in range(5):
g_num.append(i)
print("my_write:", g_num)
def my_read():
global g_num
print("my_read:", g_num)
if __name__ == '__main__':
sub_write = threading.Thread(target=my_write)
sub_read = threading.Thread(target=my_read)
sub_write.start()
time.sleep(1)
sub_read.start()
[运行结果]
my_write: [0, 1, 2, 3, 4]
my_read: [0, 1, 2, 3, 4]
线程同步: 保证同一时刻只能有一个线程去操作全局变量 同步: 就是协同步调,按预定的先后次序进行运行。
线程同步的方式:
线程等待(join)
first_thread.start()
first_thread.join() # 等待线程first_thread执行完毕再继续向下进行
second_thread.start()
互斥锁
对共享数据进行锁定,保证同一时刻只能有一个线程去操作
互斥锁的使用:
mutex = threading.Lock()
mutex.acquire()
mutex.release()