Python的GIL锁
python的GIL锁是什么?
python内置的一个全局解释器锁,锁的作用就是保证同一时刻一个进程中只有一个县城可以被cpu调度.
为什么有着吧GIL锁?
python语言的创始人在开发这门语言时,目的是快速把语言开发出来,如果加上GIL锁(C语言加锁),切换时按照100条字符串指令来进行线程间的切换.
GIL锁有几种:
1,Lock(一次放一个)
线程安全,多线程操作时,内部会让所有线程排队处理.
如: list/dict/Queue
非线程安全 + 人 =>排队处理
需求:
a,创建100个线程,在列表中追加8
b,创建100个线程
v=[]
锁
- 把自己添加到列表中.
- 在读取列表的最后一个.
解锁
所以锁一个代码块推荐使用以下代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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() for i in range(10): t =threading.Thread(target=func,args=(i,)) t.start()
2,RLock(一次放一个)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import threading import time v = [] lock = threading.RLock() def func(arg): lock.acquire() 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()
3,BoundedSemaphore(一次放N个) 又称信号量
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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()
4,Condition(一次放x个)
有两种方式:
方式,一
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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()
方式,二
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
def xxxx(): print('来执行函数了') input(">>>") # 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()
5,Event(一次放所有)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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.clear() # 再次变红灯 for i in range(10): t =threading.Thread(target=func,args=(i,)) t.start() input(">>>>") lock.set()
下面简单介绍一下:
threading.local
作用:
内部自动为每个线程维护一个空间(字典),用于当前存取属于自己的值.保证线程之间的数据隔离.
{
线程ID: {...}
线程ID: {...}
线程ID: {...}
}
示例:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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()
那么原理是怎么回事呢?
还是上代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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()