第二十九天:继承互斥锁及线程
进程互斥锁
让并发变成串行, 牺牲了执行效率, 保证了数据安全.
在程序并发执行时,需要修改数据时使用.
队列
相当于内存中产生一个队列空间,先进先出,可以存放多个数据。
堆栈
先进后出,后进先出
multiprocessing 的 Queue
# 调用队列类,实例化产生队列对象
# 传参数则代表队列存放的数据个数,不传参则代表可以有无数个
q = Queue(5)
q = Queue()
# put 添加值,队列满了则会卡住
# get() 获取数据遵循先进先出,若队列中没有数据,也会卡住
# empty() 判断队列是否位空
# get_nowait()获取队列数据,没有则报错
# put_nowait()添加数据,满了再添加则会报错
# full()判断队列是否为满
IPC
进程间通信,进程间的数据是相互隔离的,想要互通数据就可以使用队列
生产者和消费者
生产者:
生产数据的
消费者
使用数据的
程序中通过队列,生产者把数据添加到队列中,消费者从队列中获取数据
线程
线程又称为进程元或轻型进程
开启一个进程,一定会有一个线程,线程才是真正的执行者。
线程是cpu调度的基本单位,
开启线程
开启进程
- 开辟一个名称空间,每开启一个进程都会占用一份内存资源
- 会自带一个线程
在python中可以使用threading中的Thread类去开启线程
from threading import Thread
import time
# 开启线程方式1:
def task():
print('线程开启')
time.sleep(1)
print('线程结束')
# t = Thread()
if __name__ == '__main__':
# 调用Thread线程类实例化得到线程对象
t = Thread(target=task)
t.start()
# 开启线程方式2:
class MyThread(Thread):
def run(self):
print('线程开启')
time.sleep(1)
print('线程结束')
t = MyThread()
t.start()
# if __name__ == '__main__':
# t = MyThread()
# t.start()
特点
- 每个进程可以开启多个线程
- 线程的开销远小于进程
- 线程间的数据使共享的
为什么使用线程
操作系统引入进程是为了使多个程序并发执行,来改善资源利率,而引入线程,则是为了减少程序并发执行时所付出的时空开销,使操作系统具有更好的并发性,同一个进程中的多个线程可以并发执行,线程不能并行只能并发
线程互斥锁
from threading import Thread, Lock
import time
mutex = Lock()
n = 100
def task(i):
print(f'线程{i}启动...')
global n
# mutex.acquire()
temp = n
time.sleep(0.1) # 一共等待10秒
n = temp-1
print(n)
# mutex.release()
if __name__ == '__main__':
t_l=[]
for i in range(100):
t = Thread(target=task, args=(i, ))
t_l.append(t)
t.start()
for t in t_l:
t.join()
# 100个线程都是在100-1
print(n)
从线程互斥锁中我们可以的出线程之间的数据是共享的