GIL 信号量 Event事件 池

发布时间 2023-10-31 22:16:44作者: 朱饱饱


不是保证数据安全,是保证线程与线程之间那个垃圾回收机制的安全
1.gil不是Python的特点,是cpython解释器的特点
2.gil是保证解释器级别的数据的安全
3.gil会导致同一个进程下的多个线程无法同时执行即无法利用多核优势
4.针对不同的数据需要加不同的锁处理
5.解释器型语言的通病:同一个进程下多个线程无法利用多核优势

递归锁特点 了解
可以被连续的acquire和release
但是只能被第一个抢到这把锁的执行上述操作
他的内部有一个计数器 每acquire一次计数加一,每release一次计数减一
只要计数不为0 那么其他人都无法抢到该锁

信号量:
sm=Semaphore(5)括号内写几,就是几个坑位
def task(name):
sm.acquire() 抢锁
print('%s 正在蹲坑'%name)
time.sleep(random.randint(1,5))
模拟蹲坑的时间,每人时间不同
sm.release()释放锁

if __name__=='__main__':
for i inrange(20):
t=Thread(target=task,args=('伞兵%s号'%i,))
t=start()
event.set()告诉等待红灯的人可以走了
event.wait()等待别人给你发信号

线程q
同一个进程下多个线程数据是共享的
为什么先同一个进程下还会去使用队列呢,因为队列是管道+锁,所以用队列还是为了保证数据的安全

队列q,先进先出
生成队列:q=queue.Queu(3)
q.put()放 数据
q.get()取数据
q.get_nowait()等
后进先出q:或者堆栈:
q=queue.LifoQueue() 或者last in first out
优先级q,可以给放入队列中的数据设置进出的优先级:
q=queue.PriorityQueue(3)
q.put((10,'111'))
q.put((-1,'1222')) 数字越小 优先级越高,第一个数字是表示优先级

什么是池:是为了保证计算机硬件的安全
进程池:
from concurrent.futures import ThraedPoolExecutor,ProcessPoolExecutor
#导入线程池和进程池
import time


pool=ThreadPoolExecutor (5)#里面数字写5,池子里造出来之后会固定5个线程,这5个人不会重复创建和销毁过程,如果不写数字,默认是会开设当前计算机CPU个数的5倍的线程
池子的使用:只需要将需要做的任务往池子中提交即可,自动会有人来服务

def task(n):
print(n)
time.sleep(2)
return n**n
pool.submit(task,1)#朝池子中提交任务 异步提交
print('主')
t_list=[ ]
for i in range(20):
res=pool.submit(task,i) 返回值是一个对象,相当于是一个类的对象,future是一个类,这个对象有个方法叫result方法,
#print(res.result())会出现 1 none 2none。。
结果出现了串行,调用这个方法程序由并发变成串行,任务的结果是有task函数的结果,所以要在函数内return,就变成了同步操作
如果想不在原地等待,
t_list.append(res)
pool.shutdown()1.关闭线程池2.等待线程池中所有任务运行完毕
for t in t_list:
print ('>>>:',t.result())
结果是有序的

线程池:
大致是相同的
from concurrent.futures import ThraedPoolExecutor,ProcessPoolExecutor
#导入线程池和进程池
import time
pool.ProcessPoolExecutor()括号内可以传数字,不传默认是CPU的个数进程
def call_back:
peint('call_back:'n.result())
res=pool.submit(task,i).add_done_callback(call_back)异步回调函数