線程鎖:
Lock :原始鎖,目前可用的最低級的同步原語
Rlock :可重入鎖
class threading.Lock
class threading.RLock
實例方法:
acquire(blocking=True, timeout=-1) 嘗試鎖定
release() :釋放鎖,如果嘗試釋放沒有鎖定的鎖會raise RuntimerError 異常
加鎖的目的
多個不同的線程能夠訪問同一個變量中的數據,爲了不讓訪問的數據混亂,所以加鎖,簡單來說就是臨界資源,必須一個訪問完了,另一個才能來訪問,所以加個鎖
死鎖問題:
循環依賴就是死鎖的必要條件
儘可能保證每一個 線程只能同時保持一個鎖,這樣程序就不會被死鎖問題所困擾
Lock 和RLock區別 (同一線程!!!)
簡單來說 Lock 屬於全局的, RLock屬於線程,
簡單認爲Rlock裏存在一個鎖定池和一個計數器,只要acquire、release成對出現就行(+1 /-1) 0表示未鎖定
同一個線程中,
Lock.acquire()
Lock.acquire()
Lock.release()
Lock.release()
這種情況會出現死鎖,因爲互斥的關係,加鎖必須釋放,才能再加鎖
RLock.acquire()
RLock.acquire()
RLock.release()
RLock.release()
RLock不會出現這種情況,在同一線程中
測試代碼在thread_lock_test.py
condition 類
一些問題互斥鎖搞不定,該類提供一些對複雜問題的同步問題的支持
通常與一個鎖關聯。需要在多個Contidion中共享一個鎖時,可以傳遞一個Lock/RLock實例給構造方法,否則它將自己生成一個RLock實例。
條件變量服從 上下文管理協議:使用 with 語句會在它包圍的代碼塊內獲取關聯的鎖
class threading.Condition(lock=None)
除了實現Lock() Rlock() 的方法外,還提供以下方法
在調用以下方法時沒有獲得鎖,將會引發 RuntimeError 異常
1.wait(timeout=None) :釋放鎖,進去condition的等待池等待通知(其他線程調用notify/notify_all 喚醒它 ,)一旦被喚醒或者超時,它重新獲得鎖並返回。
2.notify():通知等待池,激活一個線程,不釋放鎖
3.notify_all():通知等待池,激活所有的線程,不釋放鎖
只能是一個線程執行過了wait(),在被阻塞過程中,另一個線程執行了notify()纔可以
信號量對象
class threading.Semaphore(value=1)
一個信號量管理一個內部計數器,該計數器因 acquire() 方法的調用而-1,因 release() 方法的調用而+1。 計數器的值永遠不會小於零;當 acquire() 方法發現計數器爲零時,將會阻塞,直到其它線程調用 release() 方法。
class threading.BoundedSemaphore(value=1)
BoundedSemaphore與Semaphore的唯一區別在於前者將在調用release()時檢查計數 器的值是否超過了計數器的初始值,如果超過了將拋出一個異常
定時器對象
class threading.Timer(interval, function, args=None, kwargs=None)
與線程一樣,通過調用 start() 方法啓動定時器。而 cancel() 方法可以停止計時器(在計時結束前), 定時器在執行其操作之前等待的時間間隔可能與用戶指定的時間間隔不完全相同。
cancel()¶
停止定時器並取消執行計時器將要執行的操作。僅當計時器仍處於等待狀態時有效。
事件對象
class threading.Event
is_set()
當且僅當內部標誌爲true時返回trueset()
set()
將內部標誌設置爲true
clear()
將內部標誌設置爲false
wait(timeout=None)
阻塞線程直到內部變量爲true,
如果調用時內部標誌爲true,將立即返回
隊列使用
創建一個“隊列”對象
import Queue
q = Queue.Queue(maxsize = 10)
Queue.Queue類即是一個隊列的同步實現。隊列長度可爲無限或者有限。可通過Queue的構造函數的可選參數maxsize來設定隊列長度。如果maxsize小於1就表示隊列長度無限。
將一個值放入隊列中
q.put(10)
調用隊列對象的put()方法在隊尾插入一個項目。put()有兩個參數,第一個item爲必需的,爲插入項目的值;第二個block爲可選參數,默認爲
1。如果隊列當前爲空且block爲1,put()方法就使調用線程暫停,直到空出一個數據單元。如果block爲0,put方法將引發Full異常。
將一個值從隊列中取出
q.get()
調用隊列對象的get()方法從隊頭刪除並返回一個項目。可選參數爲block,默認爲True。如果隊列爲空且block爲True,get()就使調用線程暫停,直至有項目可用。如果隊列爲空且block爲False,隊列將引發Empty異常。
Python Queue模塊有三種隊列及構造函數:
1、Python Queue模塊的FIFO隊列先進先出。 class queue.Queue(maxsize)
2、LIFO類似於堆,即先進後出。 class queue.LifoQueue(maxsize)
3、還有一種是優先級隊列級別越低越先出來。 class queue.PriorityQueue(maxsize)
此包中的常用方法(q = Queue.Queue()):
q.qsize() 返回隊列的大小
q.empty() 如果隊列爲空,返回True,反之False
q.full() 如果隊列滿了,返回True,反之False
q.full 與 maxsize 大小對應
q.get([block[, timeout]]) 獲取隊列,timeout等待時間
q.get_nowait() 相當q.get(False)
非阻塞 q.put(item) 寫入隊列,timeout等待時間
q.put_nowait(item) 相當q.put(item, False)
q.task_done() 在完成一項工作之後,q.task_done() 函數向任務已經完成的隊列發送一個信號
q.join() 實際上意味着等到隊列爲空,再執行別的操作
lock/rlock
condition 類測試
信號量類測試
定時器對象
事件對象
隊列