PYTHON NOTES · 10
掌握多任务、进程、线程、守护任务、数据共享与互斥锁。
- 进程
- 线程
Python 进程与线程
掌握多任务、进程、线程、守护任务、数据共享与互斥锁。
1、多任务
同一时间内执行多个任务
1.并行
真正的同一时间进行多个任务——进程
2.并发
一段时间内交替进行多个任务——线程
2、进程
1.创建进程
multiprocessing.Process(target="执行的内容",name="进程名",
args=“位置参数”,kwargs=“关键字参数”,daemond=True(守护进程))
import time
import multiprocessing
def lisen():
for i in range(20):
print("我在听歌")
time.sleep(1)
def write():
for i in range(20):
print("我在写代码")
time.sleep(1)
if __name__ == '__main__':
# 创建进程
p1 = multiprocessing.Process(target=lisen)
p2 = multiprocessing.Process(target=write)
#开始进程
p1.start()
p2.start()
2. 进程ID
#获取pid os.pid
#获取父进程id os.ppid
import os
import time
def lisen():
print("听歌的进程id",os.getpid())
print("听歌的父进程id",os.getppid())
for i in range(20):
print("我在听歌")
time.sleep(1)
def write():
print("写代码的进程id",os.getpid())
print("写代码的父进程id",os.getppid())
for i in range(20):
print("我在写代码")
time.sleep(1)
import multiprocessing
if __name__ == '__main__':
print("主进程的进程id",os.getpid())
print("主进程的父进程id",os.getppid())
# 创建进程
p1 = multiprocessing.Process(target=lisen)
p2 = multiprocessing.Process(target=write)
#开始进程
p1.start()
p2.start()
3.进程之间的数据共享
主进程的全局变量子进程无法访问
子进程会自己复制一份主进程的变量
如果要全局访问同一变量,需要使用通道
#进程之前如果想进行数据传输就需要用到管道
import multiprocessing
import time
#新建一个管道
queue=multiprocessing.Queue()
#管道可以有多个
queue2=multiprocessing.Queue()
def fn1(queue):
for i in range(5):
#给管道里面放数据
queue.put(i)
time.sleep(0.5)
print(queue)
def fn2(queue):
for i in range(5):
#从管道里面取数据
print(queue.get())
time.sleep(0.5)
if __name__ == '__main__':
p1=multiprocessing.Process(target=fn1,args=(queue,))
p2=multiprocessing.Process(target=fn2,args=(queue,))
p1.start()
p2.start()
4. 守护进程
主进程会等待子进程结束后再结束
守护进程:主进程结束时子进程也结束
方法:1.守护进程属性
2.强制结束
import time
import multiprocessing
#现象:主进程结束,子进程会继续执行,直到子进程结束,
# 主进程等待子进程
#守护进程:主进程结束,子进程立刻结束
#方法1:给子进程设置守护进程属性 daemon=True
#方法2:强制关闭子进程 process.terminate()
def eat():
for i in range(10):
print("吃吃吃")
time.sleep(0.5)
def drink():
for i in range(10):
print("喝喝喝")
time.sleep(0.5)
if __name__ == '__main__':
p1=multiprocessing.Process(target=eat)
p2=multiprocessing.Process(target=drink)
# #设置守护进程属性
# p1=multiprocessing.Process(target=eat,daemon=True)
# p2=multiprocessing.Process(target=drink,daemon=True)
p1.start()
p2.start()
for i in range (5):
print("玩玩玩")
time.sleep(0.5)
## 强制删除子进程
p1.terminate()
p2.terminate()
3、线程
1.特点
线程的执行是无序的
主线程会等子线程结束再结束
线程之间共享全局变量
线程访问全局变量会出现错误
2.创建多线程任务
threading.Thread(target="执行的内容",name="进程名",
args=“位置参数”,kwargs=“关键字参数”,daemond=True(守护进程)
import time
import threading
def eat():
for i in range(10):
print("吃吃吃")
time.sleep(0.5)
def drink():
for i in range(10):
print("喝喝喝")
time.sleep(0.5)
if __name__ == '__main__':
p1=threading.Thread(target=eat)
p2=threading.Thread(target=drink)
p1.start()
p2.start()
3.守护多线程
结束的最小单位是程序(进程)
线程要守护就都守护,否则无效
线程不能强制关闭
import time
import threading
def eat():
for i in range(10):
print("吃吃吃")
time.sleep(0.5)
def drink():
for i in range(10):
print("喝喝喝")
time.sleep(0.5)
if __name__ == '__main__':
#添加守护线程属性
p1=threading.Thread(target=eat,daemon=True)
p2=threading.Thread(target=drink, daemon= True)
p1.start()
p2.start()
for i in range(5):
print("打豆豆")
time.sleep(0.5)
4. 线程之间的数据共享
线程之间可以全局变量共享,
但由于线程的执行是无序的,所以会导致数据错误
# 抢票
import threading
import time
num=3
def run():
global num
num-=1
print(f"{threading.current_thread().name}抢到一张票,还剩{num}张票")
if __name__ == '__main__':
t1=threading.Thread(target=run,name="线程1")
t2=threading.Thread(target=run,name="线程2")
t3=threading.Thread(target=run,name="线程3")
t4=threading.Thread(target=run,name="线程4")
t5=threading.Thread(target=run,name="线程5")
t1.start()
t2.start()
t3.start()
t4.start()
t5.start()
5.互斥锁
为解决线程共享全局变量导致数据错误的情况,
可以给函数内增加锁,
锁的作用是让线程一口气执行完这一段代码,以防数据错误
# 抢票
import threading
num=3
def run(lock):
#添加锁
# lock.acquire()
#托管锁
with lock:
global num
if num >0:
num-=1
print(f"{threading.current_thread().name}抢到一张票,还剩{num}张票")
# #解锁
# lock.release()
if __name__ == '__main__':
#添加互斥锁
lock=threading.Lock()
t1=threading.Thread(target=run,name="线程1",args=(lock,))
t2=threading.Thread(target=run,name="线程2",args=(lock,))
t3=threading.Thread(target=run,name="线程3",args=(lock,))
t4=threading.Thread(target=run,name="线程4",args=(lock,))
t5=threading.Thread(target=run,name="线程5",args=(lock,))
t1.start()
t2.start()
t3.start()
t4.start()
t5.start()