1。今天讲了一下线程安全的问题 线程安全的有,列表,字典,队列(队列在后面生产者消费者模型里有)
2.锁,最普通的锁 lock
import threading import time v = [] lock = threading.Lock() def func(arg): lock.acquire() #这个只能锁一次,如果锁两次及以上就会锁死 v.append(arg) time.sleep(0.01) m = v[-1] print(arg,m) lock.release() #这个正常解锁一次就OK了,上边锁多了,下面怎么也解不开 for i in range(10): t =threading.Thread(target=func,args=(i,)) t.start()
3,锁,用的最多的锁 Rlock
import threading import time v = [] lock = threading.RLock() def func(arg): lock.acquire() #这个可以锁2次 及以上 lock.acquire() v.append(arg) time.sleep(0.01) m = v[-1] print(arg,m) lock.release()#上面锁几次这就解几次 lock.release() for i in range(10): t =threading.Thread(target=func,args=(i,)) t.start()
4,锁,名字最长的锁
import time import threading lock = threading.BoundedSemaphore(3) #你这里写多少,他就一次走几个线程 def func(arg): lock.acquire() print(arg) time.sleep(1) lock.release() for i in range(20): t =threading.Thread(target=func,args=(i,)) t.start()
5.锁,
import time import threading lock = threading.Condition() # ############## 方式一 ############## def func(arg): print('线程进来了') lock.acquire() #这个锁还是必加的 lock.wait() # 加锁 这里新加的锁,在多写一个主线程 print(arg) time.sleep(1) lock.release() #同上 for i in range(10): t =threading.Thread(target=func,args=(i,)) t.start() while True: inp = int(input('>>>')) #一次输入多少就执行多少线程 lock.acquire() #同上 lock.notify(inp) #固定写法 lock.release() #同上 # ############## 方式二 ############## """ def xxxx(): print('来执行函数了') input(">>>") #这个智能一点,在这里可以等到执行一个with open 等。。。然后才返回值,返回什么还可以再随机 # ct = threading.current_thread() # 获取当前线程 # ct.getName() return True def func(arg): print('线程进来了') lock.wait_for(xxxx) #一直在等,等某个条件满足了,就往下走 print(arg) time.sleep(1) for i in range(10): t =threading.Thread(target=func,args=(i,)) t.start()
6,锁,
import time import threading lock = threading.Event() def func(arg): print('线程来了') lock.wait() # 加锁:红灯 print(arg) for i in range(10): t =threading.Thread(target=func,args=(i,)) t.start() input(">>>>") lock.set() # 绿灯 只要没有绿灯就一直锁死,只要绿灯过一次 lock.wait() #只要绿灯过一次,这里再写几个也没用,只有clear有用 lock.clear() # 再次变红灯 for i in range(10): t =threading.Thread(target=func,args=(i,)) t.start() input(">>>>") lock.set()
7. threading.local()
import time import threading v = threading.local() def func(arg): # 内部会为当前线程创建一个空间用于存储:phone=自己的值 会为每一个线程储存一个空间 v.phone = arg time.sleep(2) print(v.phone,arg) # 去当前线程自己空间取值 这两个值一样 for i in range(10): t =threading.Thread(target=func,args=(i,)) t.start()
8.threadinglocal原理
import time import threading DATA_DICT = {} def func(arg): ident = threading.get_ident() 获取当前线程ID #c= threading.current_thread() 获取当前线程对象 DATA_DICT[ident] = arg time.sleep(1) print(DATA_DICT[ident],arg) for i in range(10): t =threading.Thread(target=func,args=(i,)) t.start()
9.threadinglocal为每个线程维护一个空间(字典),用于当前线程存取自己的值,保证线程之间的数据隔离 {线程id:{自己的key:自己的value}}
import time import threading INFO = {} class Local(object): def __getattr__(self, item): ident = threading.get_ident() return INFO[ident][item] def __setattr__(self, key, value): ident = threading.get_ident() if ident in INFO: INFO[ident][key] = value else: INFO[ident] = {key:value} obj = Local() def func(arg): obj.phone = arg # 调用对象的 __setattr__方法(“phone”,1) time.sleep(2) print(obj.phone,arg) for i in range(10): t =threading.Thread(target=func,args=(i,)) t.start() 每个对象都是调用上面的方法 def __getitem__(self,item) obj['x'] def __getattr__(self,item) obj.x 执行了他就等于执行attr x=item def __setattr__(self,key,value): obj.x=6 这个key是x value是6
10.小数据池
from concurrent.futures import ThreadPoolExecutor import time def task(a1,a2): time.sleep(2) print(a1,a2) # 创建了一个线程池(最多5个线程) pool = ThreadPoolExecutor(5) for i in range(40): # 去线程池中申请一个线程,让线程执行task函数。 pool.submit(task,i,8) for i in range(10): 同比这个来讲的话 下面的对象这个要等于一下,arsg传值,上面的 一个submit就全搞定了 t =threading.Thread(target=func,args=(i,)) t.start()
11.生产者消费者模型
用户是生产者,程序是消费者 生产者把东西放在这里,客户端接收到了就去工作
解决了一直等待的问题,让客服端和服务端不用直接交互,放在队列里互相等待