Lock 互斥鎖
請求鎖 - 進(jìn)入鎖定池 - 獲取鎖 - 鎖定 - 釋放鎖
Lock處于鎖定狀態(tài)時(shí),不被特定的線程擁有阴挣。
acquire([timeout]): 使線程進(jìn)入同步阻塞狀態(tài),嘗試獲得鎖定啰扛。
release(): 釋放鎖扭倾。使用前線程必須已獲得鎖定,否則將拋出異常。
RLock 可重入鎖
可以被同一個(gè)線程請求多次的同步指令
RLock使用了“擁有的線程”和“遞歸等級”的概念,處于鎖定狀態(tài)時(shí),RLock被某個(gè)線程擁有膜蛔。擁有RLock的線程可以再次調(diào)用acquire(),釋放鎖時(shí)需要調(diào)用release()相同次數(shù)处硬。
可以認(rèn)為RLock包含一個(gè)鎖定池和一個(gè)初始值為0的計(jì)數(shù)器,每次成功調(diào)用 acquire()/release(),計(jì)數(shù)器將+1/-1,為0時(shí)鎖處于未鎖定狀態(tài)。
Semaphore 共享對象訪問
管理一個(gè)內(nèi)置的計(jì)數(shù)器 獲取鎖 +1 釋放鎖 -1 當(dāng)計(jì)數(shù)器等于0的時(shí)候 獲取鎖阻塞等待
import time
import threading
semaphore = threading.Semaphore(3)
def func():
if semaphore.acquire():
for i in range(3):
time.sleep(1)
print (threading.currentThread().getName() + '獲取鎖')
semaphore.release()
print (threading.currentThread().getName() + ' 釋放鎖')
for i in range(5):
t1 = threading.Thread(target=func)
t1.start()
Event 線程間通信
Event內(nèi)部包含了一個(gè)標(biāo)志位,初始的時(shí)候?yàn)閒alse蛙紫。
可以使用使用set()來將其設(shè)置為true;
或者使用clear()將其從新設(shè)置為false;
可以使用is_set()來檢查標(biāo)志位的狀態(tài);
另一個(gè)最重要的函數(shù)就是wait(timeout=None),用來阻塞當(dāng)前線程,直到event的內(nèi)部標(biāo)志位被設(shè)置為true或者timeout超時(shí)拍屑。如果內(nèi)部標(biāo)志位為true則wait()函數(shù)理解返回。
Condition 線程同步
可以把Condition理解為一把高級的瑣,它提供了比Lock, RLock更高級的功能,允許我們能夠控制復(fù)雜的線程同步問題坑傅。threadiong.Condition在內(nèi)部維護(hù)一個(gè)瑣對象(默認(rèn)是RLock),可以在創(chuàng)建Condigtion對象的時(shí)候把瑣對象作為參數(shù)傳入僵驰。Condition也提供了acquire, release方法,其含義與瑣的acquire, release方法一致,其實(shí)它只是簡單的調(diào)用內(nèi)部瑣對象的對應(yīng)的方法而已。Condition還提供了如下方法(特別要注意:這些方法只有在占用瑣(acquire)之后才能調(diào)用,否則將會(huì)報(bào)RuntimeError異常唁毒。):
Condition.wait([timeout]):
wait方法釋放內(nèi)部所占用的瑣,同時(shí)線程被掛起,直至接收到通知被喚醒或超時(shí)(如果提供了timeout參數(shù)的話)蒜茴。當(dāng)線程被喚醒并重新占有瑣的時(shí)候,程序才會(huì)繼續(xù)執(zhí)行下去。
Condition.notify():
喚醒一個(gè)掛起的線程(如果存在掛起的線程)浆西。注意:notify()方法不會(huì)釋放所占用的瑣粉私。
Condition.notify_all()
Condition.notifyAll()
喚醒所有掛起的線程(如果存在掛起的線程)。注意:這些方法不會(huì)釋放所占用的瑣近零。
from threading import Thread, Condition
import time
import random
queue = []
MAX_NUM = 10
condition = Condition()
class ProducerThread(Thread):
def run(self):
nums = range(5)
global queue
while True:
condition.acquire()
if len(queue) == MAX_NUM:
print ("Queue full, producer is waiting" )
condition.wait()
print ("Space in queue, Consumer notified the producer" )
num = random.choice(nums)
queue.append(num)
print ("Produced", num)
condition.notify()
condition.release()
time.sleep(random.random())
class ConsumerThread(Thread):
def run(self):
global queue
while True:
condition.acquire()
if not queue:
print ("Nothing in queue, consumer is waiting")
condition.wait()
print "Producer added something to queue and notified the consumer"
num = queue.pop(0)
print ("Consumed", num)
condition.notify()
condition.release()
time.sleep(random.random())
ProducerThread().start()
ConsumerThread().start()