#【记住】
#队列的特点和实现原理
#特点:
#1、进程之间的通信
#2、数据安全
#3、先进先出
#实现原理
#基于管道+锁
#管道 基于文件级别的socket+pickle实现
#生产者消费者模型如何实现?
#使用场景:
#采集图片,爬取音乐,为了提高效率,抓取网页的过程是生产者,分析网页形成数据的的过程是消费者
#监控系统,监控程序作为生产者,发送监控邮件报警,是消费者
#生产者把邮件信息交给消息中间件redis,消费者从中间件中取值,然后发送邮件
#框架:celery:可以做定时任务
#进程在计算机中扮演的角色
#资源分配的最小单位,线程是操作系统调度的最小单位
#进程之间内存隔离
#多个进程之间是竞争的关系
#进程三状态之间的转换,尽量减少io操作,可以用argv操作,避免 input
#让我们程序运行过程中尽可能多的使用cpu资源
#为什么线程之间数据不安全
#首先线程之间数据共享,共享主进程中的资源
#如果线程中有赋值操作,操作代码在底层不是由一条完整的cpu指令完成,dis可以查看python代码底层指令
#如果是if判断等语句,底层也不是由一条完整指令完成,这中间发生了GIL锁的切换(时间片轮转),可能导致数据不安全
# import dis
# def func(a):
# if a>0:
# print(a)
# else :print(0)
# print(dis.dis(func))
#死锁
#发生在多个线程,多个锁(资源需求)之间
#当A,B线程都需要a和b资源,某一时间,A拿到了a,B拿到了b,2个线程就一直等待下去
#锁有叠加
#queue是线程安全的 还有logging
#数据n共享,但是不安全,出现了 -= += ,最终输出啥的都有
from threading import Thread,Lock
n = 0
def func1(lock):
global n
for i in range(100000):
n += 1
def func2(lock):
global n
for i in range(100000):
n -= 1
if __name__ == '__main__':
t1 = Thread(target=func1)
t2 = Thread(target=func2)
t1.start()
t2.start()
t1.join()
t2.join()
print(n)
#加锁,输出为0
from threading import Thread,Lock
n = 0
def func1(lock):
global n
with lock:
for i in range(100000):
n += 1
def func2(lock):
global n
with lock:
for i in range(100000):
n -= 1
if __name__ == '__main__':
lock = Lock()
t1 = Thread(target=func1,args=(lock,))
t2 = Thread(target=func2,args=(lock,))
t1.start()
t2.start()
t1.join()
t2.join()
print(n)
#判断numbers最终长度是否一定为1,好像是的
import time
import threading
loop = int(1E5)
def _add(loop:int = 1):
global numbers
for _ in range(loop):
numbers.append(0)
def _sub(loop:int = 1):
global numbers
for _ in range(loop):
while not numbers:
time.sleep(1E-6)
numbers.pop()
numbers=[0]
t1 = threading.Thread(target=_add,args=(loop,))
t2 = threading.Thread(target=_sub,args=(loop,))
t1.start()
t1.join()
t2.start()
t2.join()
print(len(numbers))
#池
#为什么要用池?
#如果先开好进程或者线程,那么有任务之后就可以直接使用这个池中的数据了
#并且开好的线程或者进程会一直存在池中,可以被多个任务反复利用
#极大的减少了开启,关闭,调度线程 和 进程的时间开销
#池中的进程或者线程个数控制了操作系统需要调度的任务个数,控制池中的单位
#有利于提高操作系统的效率,减轻操作系统的负担
#模块 concurrent.futures,平时启动进程池的机会不多,一般启动线程池
import time
import random
from threading import current_thread
from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
def func():
print(f'{current_thread().ident} start')
time.sleep(random.randint(1,3))
print(f'{current_thread().ident} end')
tp = ThreadPoolExecutor(5) #cpu + 1 个线程的线程池
for i in range(10):
tp.submit(func)
#线程池里只有5个线程在运行,线程与线程之间不影响,一个结束,就马上处理下一个任务