day 42(锁 + )
锁:
经典面试题
# # GIL # # 锁 import time from threading import Thread,Lock def func(lock): global n # lock.acquire() temp = n #在这里睡了一秒,所以程序会进入就绪状态,下面又是同步运行,但是上面可以异步运行(global n 和 temp = n) # time 会让程序重新进入就绪状态,每一次执行子线程,都会改变global n,而不是真正的n time.sleep(0.1) n = temp -1 # lock.release() n = 100 t_lst = [] lock = Lock() # 锁 for i in range(100): t = Thread(target=func,args=(lock,)) t.start() t_lst.append(t) for t in t_lst:t.join() #让所有线程变成同步的 print(n) # 数据是不隔离 # from threading import Thread # # def func(): # global n # temple = n # n = temple - 1 # # n = 100 # for i in range(100): # t = Thread(target = func) # t.start() # print(n)
互斥锁:
from threading import Thread,Lock
lock = Lock()
lock.acquire()
lock.acquire()
lock.acquire()
lock.release()
# 卡住了(阻塞了)
科学家吃面问题:
# from threading import Lock
#
# lock= Lock() # 在同一个线程中
# # 能够被一个锁的多个acquire阻塞住了
# # 这种锁就叫做互斥锁
# lock.acquire()
# lock.acquire()
# 科学家吃面问题
# 要完成一件事情 需要两个必要因素
# 要想吃到面 叉子 面
# 资源的互相抢占的问题 —— 死锁
# import time
# from threading import Thread,Lock
# def eat1(noodle_lock,fork_lock,name):
# noodle_lock.acquire()
# print('%s抢到了面'%name)
# fork_lock.acquire()
# print('%s抢到了叉子'%name)
# print('%s正在吃面'%name)
# fork_lock.release()
# print('%s归还了叉子' % name)
# noodle_lock.release()
# print('%s归还了面' % name)
#
# def eat2(noodle_lock,fork_lock,name):
# fork_lock.acquire()
# print('%s抢到了叉子' % name)
# time.sleep(0.5)
# noodle_lock.acquire()
# print('%s抢到了面'%name)
# print('%s正在吃面'%name)
# noodle_lock.release()
# print('%s归还了面' % name)
# fork_lock.release()
# print('%s归还了叉子' % name)
#
# if __name__ == '__main__':
# noodle_lock = Lock()
# fork_lock = Lock()
# Thread(target=eat1,args=(noodle_lock,fork_lock,'yuan')).start()
# Thread(target=eat2,args=(noodle_lock,fork_lock,'egon')).start()
# Thread(target=eat1,args=(noodle_lock,fork_lock,'nezha')).start()
# Thread(target=eat2,args=(noodle_lock,fork_lock,'alex')).start()
# 递归锁
# from threading import Thread,RLock
# # 在同一个线程中对同一个锁多次acquire不会产生阻塞
# # 递归锁
# def func(rlock,flag):
# rlock.acquire()
# print(flag*10)
# rlock.acquire()
# print(flag * 10)
# rlock.acquire()
# print(flag * 10)
# rlock.acquire()
# print(flag * 10)
# rlock.release()
# rlock.release()
# rlock.release()
# rlock.release()
# rlock = RLock()
# Thread(target=func,args=(rlock,'*')).start()
# Thread(target=func,args=(rlock,'-')).start()
import time
from threading import Thread,RLock
def eat1(noodle_lock,fork_lock,name):
noodle_lock.acquire()
print('%s抢到了面'%name)
fork_lock.acquire()
print('%s抢到了叉子'%name)
print('%s正在吃面'%name)
fork_lock.release()
print('%s归还了叉子' % name)
noodle_lock.release()
print('%s归还了面' % name)
def eat2(noodle_lock,fork_lock,name):
fork_lock.acquire()
print('%s抢到了叉子' % name)
time.sleep(0.5)
noodle_lock.acquire()
print('%s抢到了面'%name)
print('%s正在吃面'%name)
noodle_lock.release()
print('%s归还了面' % name)
fork_lock.release()
print('%s归还了叉子' % name)
if __name__ == '__main__':
fork_lock = noodle_lock = RLock()
Thread(target=eat1,args=(noodle_lock,fork_lock,'yuan')).start()
Thread(target=eat2,args=(noodle_lock,fork_lock,'egon')).start()
Thread(target=eat1,args=(noodle_lock,fork_lock,'nezha')).start()
Thread(target=eat2,args=(noodle_lock,fork_lock,'alex')).start()
# 有超过一个资源需要锁的时候 —— 递归锁
# 递归锁的应用场景
# 互斥锁和递归锁的区别
import time
import random
from threading import Event,Thread
# wait()
# set clear isset
# 连接数据库
def connect_db(e):
count = 1
while count < 4: #第一次进入默认是False
print('尝试第%s次检测连接'%count)
e.wait(0.5)
# 如果不传参数会一直等到事件为True为止
# 如果传参数 传一个时间参数
count += 1
if e.is_set():
print('连接成功')
break
else:
print('连接失败')
def check_conn(e):
'''检测数据库是否可以连接'''
time.sleep(random.randint(1,2))
e.set() 此题:如果小于1.5 会把状态False 改为 True ,否则会执行else:结束程序
e = Event()
Thread(target=check_conn,args=(e,)).start()
Thread(target=connect_db,args=(e,)).start()
# 你要做一件事情 是有前提的
# 你就先去处理前提的问题 —— 前提处理好了 把状态设置成True
# 来控制即将要做的事情可以开始
条件和定时器:
from threading import Condition,Thread
# # acquire release
# # notify -- wait的行为
# # 10线程 wait
# # notify(1)
# def func(i,con):
# con.acquire()
# con.wait()
# print(i*'*')
# con.release()
#
# con = Condition()
# for i in range(10):
# Thread(target=func,args=(i,con)).start()
# while True:
# n = int(input('>>>'))
# con.acquire()
# con.notify()
# con.release()
#
# con.acquire()
# con.notify_all()
# con.release()
# semaphore 允许统一是个n个线程执行这段代码
# event 有一个内部的事件来控制wait的行为
#控制的是所有的线程
# condition 有一个内部的条件来控制wait的行为
#可以逐个或者分批次的控制线程的走向
from threading import Timer
def func():
print('*'*20)
t = Timer(5,func) # 要开启一个线程,等到5秒钟之后才开启并且执行
t.start()
print('-'*10)
print('^'*10)
队列:
import queue
q = queue.LifoQueue()
q = queue.Queue()
q.put('first')
q.put((1,2))
q.put([1,2])
q.put({'k':'v'})
q.put(lambda :1)
print(q.get())
print(q.get())
print(q.get())
print(q.get())
q = queue.PriorityQueue()
q.put((1,'a')) #数字越小优先级越高
q.put((20,'z'))
q.put((20,'b'))
print(q.get())
print(q.get())
print(q.get())
线程池:
# import time
# from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
# def func(i):
# print(i*'*')
# time.sleep(1)
# return i**2
#
# def callb(arg):
# print(arg.result()*'-')
#
# if __name__ == '__main__':
# # thread_pool = ThreadPoolExecutor(5)
# thread_pool = ThreadPoolExecutor(5)
# # ret_lst = []
# for i in range(10):
# thread_pool.submit(func,i).add_done_callback(callb) # 相当于apply_async
# # ret = thread_pool.submit(func,i).add_done_callback(callable) # 相当于apply_async
# # ret_lst.append(ret)
# thread_pool.shutdown() # close+join
# # for ret in ret_lst:
# # print(ret.result())
# print('wahaha')
# # 回调函数
# 进程池
# 线程池
# 当内存不需要共享,且高计算的时候 用进程
# 当内存需要共享,且高IO的时候 用线程
# 当并发很大的时候
# 多进程 : 多个任务 —— 进程池 :cpu个数、cpu个数+1
# 多线程 :多个任务 —— 线程池 :cpu个数*5
# 4C : 4个、5个进程 —— 20条线程/进程 : 80-100个任务
# 50000
# import time
# from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
#
# def fun(i):
# print(i*'*')
# time.sleep(1)
# return i**2
#
# def callc(args):
# print(args.result()*'-')
#
#
# thread_pool = ThreadPoolExecutor(5)
# for i in range(10):
# ret = thread_pool.submit(fun,i).add_done_callback(callc)
# # thread_pool.map(fun,range(10))
# thread_pool.shutdown()
# print('wahh')
import time
from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
def fun(i):
print('*'*i)
time.sleep(1)
return i**2
def callc(args):
print(args.result() * '-')
thread_pool = ThreadPoolExecutor(5)
for i in range(10):
ret = thread_pool.submit(fun,i).add_done_callback(callc)
thread_pool.shutdown()
print('主线程')