python Condition類(鎖)


Condition(條件變量)通常與一個鎖關聯。需要在多個Contidion中共享一個鎖時,可以傳遞一個Lock/RLock實例給構造方法,否則它將自己生成一個RLock實例。

不理解鎖的,請看上一條隨筆。

Condition():

  • acquire(): 線程鎖
  • release(): 釋放鎖
  • wait(timeout): 線程掛起,直到收到一個notify通知或者超時(可選的,浮點數,單位是秒s)才會被喚醒繼續運行。wait()必須在已獲得Lock前提下才能調用,否則會觸發RuntimeError。
  • notify(n=1): 通知其他線程,那些掛起的線程接到這個通知之后會開始運行,默認是通知一個正等待該condition的線程,最多則喚醒n個等待的線程。notify()必須在已獲得Lock前提下才能調用,否則會觸發RuntimeError。notify()不會主動釋放Lock。
  • notifyAll(): 如果wait狀態線程比較多,notifyAll的作用就是通知所有線程
import threading
import time

# 商品
product = None
# 條件變量
con = threading.Condition(threading.Lock())


# 生產者方法
def produce():
    global product

    if con.acquire():
        while True:
            print('我執行了,produce')
            if product is None:
                product = 'anything'
                print('produce...',product)
                print('plock=',con)
                # 通知消費者,商品已經生產
                con.notify()

            # 等待通知
            con.wait()
            time.sleep(2)


# 消費者方法
def consume():
    global product

    if con.acquire():
        while True:
            print('我執行了,consume')
            if product is not None:
                print('consume...',product)
                print('clock=',con)
                product = None

                # 通知生產者,商品已經沒了
                con.notify()

            # 等待通知
            con.wait()
            time.sleep(2)


t2 = threading.Thread(target=consume)
t2.start()
t1 = threading.Thread(target=produce)
t1.start()
1、生產者消費者模型
import threading
import time

condition = threading.Condition()
products = 0

class Producer(threading.Thread):
    def run(self):
        global products
        while True:
            if condition.acquire():
                if products < 10:
                    products += 1;
                    print "Producer(%s):deliver one, now products:%s" %(self.name, products)
                    condition.notify()#不釋放鎖定,因此需要下面一句
                    condition.release()
                else:
                    print "Producer(%s):already 10, stop deliver, now products:%s" %(self.name, products)
                    condition.wait();#自動釋放鎖定
                time.sleep(2)

class Consumer(threading.Thread):
    def run(self):
        global products
        while True:
            if condition.acquire():
                if products > 1:
                    products -= 1
                    print "Consumer(%s):consume one, now products:%s" %(self.name, products)
                    condition.notify()
                    condition.release()
                else:
                    print "Consumer(%s):only 1, stop consume, products:%s" %(self.name, products)
                    condition.wait();
                time.sleep(2)

if __name__ == "__main__":
    for p in range(0, 2):
        p = Producer()
        p.start()

    for c in range(0, 3):
        c = Consumer()
        c.start()
2、生產者消費者模型
import threading
 
alist = None
condition = threading.Condition()
 
def doSet():
    if condition.acquire():
        while alist is None:
            condition.wait()
        for i in range(len(alist))[::-1]:
            alist[i] = 1
        condition.release()
 
def doPrint():
    if condition.acquire():
        while alist is None:
            condition.wait()
        for i in alist:
            print i,
        print
        condition.release()
 
def doCreate():
    global alist
    if condition.acquire():
        if alist is None:
            alist = [0 for i in range(10)]
            condition.notifyAll()
        condition.release()
 
tset = threading.Thread(target=doSet,name='tset')
tprint = threading.Thread(target=doPrint,name='tprint')
tcreate = threading.Thread(target=doCreate,name='tcreate')
tset.start()
tprint.start()
tcreate.start()
3、生產者消費者模型
import threading
 
def run(n):
    con.acquire()
    print('我執行了',threading.current_thread().name)
    con.wait()
    print("run the thread: %s" %n)
    con.release()
 
if __name__ == '__main__':
 
    con = threading.Condition()
    for i in range(10):
        t = threading.Thread(target=run, args=(i,))
        t.start()
 
    while True:
        inp = input('>>>')

        if inp == 'q':
            break
        con.acquire()
        con.notify(int(inp))
        con.release()
View Code

 

總結

1、release和wait都有釋放鎖的作用,不同在於wait后,該子線程就在那里掛起等待,要繼續執行,就需要接收到notify或者notifyAll來喚醒線程,而release該線程還能繼續執行。

2、notify和notifyAll的區別在於,notify只能喚醒一個wait,而notifyAll能喚起所有wait。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM