【Python爬虫学习笔记11】Queue线程安全队列和GIL全局解释器锁
Queue線程安全隊列
在Python多線程編程中,雖然threading模塊為我們提供了Lock類和Condition類借助鎖機制來處理線程并發執行,但在實際開發中使用加鎖和釋放鎖仍是一個經常性的且較為繁瑣的過程。因此,Python中又為我們提供了一個使用起來更為簡單的模塊——queue模塊。
queue模塊是一個線程安全的模塊(線程安全——即不存在共享變量訪問沖突問題),該模塊提供了同步的、線程安全的隊列類,包括FIFO(先進先出)隊列Queue以及LIFO(后進先出)隊列LifoQueue。這些隊列都已經實現了鎖的原子操作(即要么不做,要么都做完),可以方便地在多線程中直接使用,實現線程間的同步。
其相關函數如下:
1.Queue(maxsize)/LifoQueue(maxsize):創建并初始化一個大小為maxsize的先進先出/后進先出的隊列。
2.qsize():返回隊列當前以存放數據的大小。
3.empty():判斷隊列是否為空。
4.full():判斷隊列是否滿了。
5.get():從隊列中取一個隊首數據。
6.put(data):將一個數據放到隊列中。
具體的使用示例如下:
##queue模塊的簡單使用示例 from queue import Queue# 初始化隊列 q = Queue(7)# 判斷隊列是否為空 print(q.empty()) #True# 存放數據 for i in range(5):q.put(i)# 輸出當前隊列大小 print(q.qsize()) #5# 判斷隊列是否為滿 print(q.full()) #False# 依次取出隊列元素并以列表形式輸出 print([q.get() for x in range(q.qsize())]) #[0,1,2,3,4] print(q.empty()) #True其實在get()方法中,還可以設置一個參數block,其代表當隊列中沒有數據時應采取的操作,默認值為True表示持續等待,如果設置為Flase則當沒有數據時拋出Empty異常。
## 設置get()方法參數block from queue import Queue,Emptyq = Queue(3) for i in range(2):q.put(i)elements = [q.get() for x in range(q.qsize())]try:x = q.get(block=False) except Empty:print('The queue is empty.') """ Output:The queue is empty. """GIL全局解釋器鎖
首先,我們先來了解一下Python自帶的解釋器——CPython。CPython解釋器是基于C語言編寫的解釋器,其的多線程機制并不是一個正真的多線程,在多核CPU中,Cpython只能利用一核而不能利用多核,即同一時刻只有一個線程在執行,而表現出多線程是因為一個CPU可以在極短的時間內輪轉執行每一個線程。
為了保證同一時刻只有一個線程在執行,在CPython解釋器中有一個叫做全局解釋器鎖GIL(Global Intepreter Lock)的東西,其主要是用于解決CPython解釋器內存管理非線程安全的問題。
而除了CPython解釋器外,還有如下其他的解釋器:
1.Jython:基于Java實現的Python解釋器,不存在GIL鎖。維基百科:https://en.wikipedia.org/wiki/Jython
2.IronPython:基于.net實現的Python解釋器,不存在GIL鎖。維基百科:https://en.wikipedia.org/wiki/IronPython
3.PyPy:基于Python實現的Python解釋器,存在GIL鎖。維基百科:https://en.wikipedia.org/wiki/PyPy
GIL雖然是真正意義上的多線程,但在處理一些IO操作(如文件讀寫和網絡請求等)時還是可以提高很多效率的,因此在IO操作上更建議使用多線程機制;然而在一些CPU計算操作上用多線程并發可能反而會使效率低下,因此在這種情況下更建議使用多進程處理。
轉載于:https://www.cnblogs.com/Unikfox/p/9708155.html
總結
以上是生活随笔為你收集整理的【Python爬虫学习笔记11】Queue线程安全队列和GIL全局解释器锁的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python基础系列讲解——继承派生和组
- 下一篇: 关于EF使用脏读(连接会话开始执行设置隔