Gil全局解释器锁
GIL是一个互斥锁(存在于Cpython),保证数据的安全(以牺牲效率换区数据的安全性)阻止同一个进程内多个线程同时执行(不能并行但是能够实现并发)并发:发起来像是同时进行的GIL全局解释器存在的原因是CPython解释器的内存管理不是线程安全的同一个进程下多个线程不能实现并行但能实现并发,多个进程下的线程可以实现并行。在IO密集的任务中 多线程优势更为明显(开启的消耗资源少)在计算密集的任务中 多进程有优势(多CPU的优势可以提现)# 计算密集型from multiprocessing import Processfrom threading import Threadimport os,timedef work(): res=0 for i in range(100): res*=iif __name__ == '__main__': l=[] print(os.cpu_count()) # 本机为8核 start=time.time() for i in range(8): # p=Process(target=work) #耗时9.252728939056396 p=Thread(target=work) #耗时35.369622230529785 l.append(p) p.start() for p in l: p.join() stop=time.time() print('run time is %s' %(stop-start))# IO密集型from multiprocessing import Processfrom threading import Threadimport threadingimport os,timedef work(): time.sleep(2)if __name__ == '__main__': l=[] print(os.cpu_count()) #本机为8核 start=time.time() for i in range(600): p=Process(target=work) #耗时4.699530839920044 # p=Thread(target=work) #耗时2.054128885269165 l.append(p) p.start() for p in l: p.join() stop=time.time() print('run time is %s' %(stop-start))
GIL全局解释器锁与普通的互斥锁的区别
对于不同的数据,要想保证安全,需要加不同的锁处理GIL并不能保证数据的安全,它是对Cpython解释器加锁,针对的是线程,让其无法并行,保证的是同一进程下多个线程间的安全线程的互斥锁保证的是数据的安全性from threading import Thread,Lockimport timemutex=Lock()n=100def task(): global n mutex.acquire() #如果不加自定义的锁,那么所有进程都得到了t=100的数据 t=n #确保t得到的是修改后的n time.sleep(0.1) n=t-1 mutex.release()lis=[] for i in range(100): q=Thread(target=task) q.start() lis.append(q)for i in lis: i.join()print(n)
死锁与递归锁
死锁就是两个线程或多个线程,得到了另一方需要获取的锁,而自身锁无法释放,导致线程的阻塞。递归锁就是,可以重复获取的锁(自定义锁只能获取(acquire)一次),每一次获取都会计数+1,直到计数为0的时候,锁才会释放,其他线程才可以抢锁。#死锁例子from threading import Thread,Lockimport timemutexA=Lock()mutexB=Lock()def task(name): mutexA.acquire()#后来线程抢占了A锁,但是B锁未得到释放,无法获取 print('A get',name) mutexB.acquire() print('B get',name) mutexA.release() print('A lose',name) mutexB.release() print('B lose',name) f1(name)def f1(name): mutexB.acquire() print('B get',name) time.sleep(0.1) #在IO的时候,其他的线程已经抢占了A锁,而B锁并未释放 mutexA.acquire() print('A get',name) mutexA.release() print('A lose',name) mutexB.release() print('B lose',name) if __name__ == '__main__': for i in range(100): p=Thread(target=task,args=(i,)) p.start()#递归锁from threading import Thread,RLockimport timemutex=RLock()#生成一个递归锁对象class MyThread(Thread): def run(self): self.f1() self.f2() def f1(self): mutex.acquire() print(self.name,1) mutex.acquire() print(self.name,2) mutex.release() mutex.release() def f2(self): mutex.acquire() print(self.name,3) time.sleep(0.5) mutex.acquire() print(self.name,4) mutex.release() mutex.release()if __name__ == '__main__': for i in range(100): p = MyThread() p.start()
信号量
#抢占厕所的例子from threading import Thread,Semaphoreimport timesm=Semaphore(5)#设定信号量为5,只能有5个线程可以继续执行def task(name): with sm: print('%s 正在上厕所') time.sleep(5)if __name__=='__main__': for i in range(20): p=Thread(target=task,args=(i,)) p.start()
event时间
from threading import Event,Threadimport timeevent=Event()def light(): print('红灯亮了') time.sleep(5) event.set() #解除阻塞 print('绿灯亮了')def car(i): print('%s 正在等红灯'%i) event.wait() #阻塞 print('%s 通行'%i) if __name__=='__main__': t=Thread(target=light) t.start() for i in range(10): c=Thread(target=car,args=(i,)) c.start()
线程queue
import queueq=queue.Queue(3)#Queue按照队列,先进先出q.put(1)q.put(2)q.put(3)print(q.get())print(q.get())print(q.get())q = queue.LifoQueue(5)#堆栈,Lifo,last in first out 先进后出q.put(1)q.put(2)q.put(3)q.put(4)print(q.get())q = queue.PriorityQueue()#PriorityQueue,优先级,数据越小,优先级越高q.put((10,'a')) q.put((-1,'b'))q.put((100,'c'))print(q.get())print(q.get())print(q.get())# -1<10<100,所以顺序是(-1, 'b'),(10, 'a'),(100, 'c')