1. 程式人生 > >執行緒通訊

執行緒通訊

使用Condition實現執行緒間通訊                                                                                                                                                       

Condition被稱為條件變數,Condition類提供了對複雜執行緒同步問題的支援,除了提供與Lock類似的acquire()和release()方法外,還提供了wait()、notify()和notify_all()方法,這些方法語法如下:

  • wait(timeout=None)。使當前執行緒釋放鎖,然後當前執行緒處於阻塞狀態,等待相同條件變數中其他執行緒喚醒或超時。timeout是設定超時時間。
  • notify()。喚醒相同條件變數中的一個執行緒。
  • notify_all()。喚醒相同條件變數中的所有執行緒。                                                                                                                              

在一個棧中,通過生產執行緒(壓棧)和消費執行緒(出棧)來控制壓棧和出棧:

import threading
import time

# 建立條件變數物件
condition = threading.Condition()


class Stack:
    def __init__(self):
        # 堆疊指標初始值為0
        self.pointer = 0
        # 堆疊有5個數字的空間
        self.data = [-1, -1, -1, -1, -1]

    # 壓棧方法
    def push(self, c):
        global condition
        condition.acquire()
        # 堆疊已滿,不能壓棧
        while self.pointer == len(self.data):
            # 等待其它執行緒把資料出棧
            condition.wait()
        # 通知其他執行緒把資料出棧
        condition.notify()
        # 資料壓棧
        self.data[self.pointer] = c
        # 指標向上移動
        self.pointer += 1
        condition.release()

    # 出棧方法
    def pop(self):
        global condition
        condition.acquire()
        # 堆疊無資料,不能出棧
        while self.pointer == 0:
            # 等待其他執行緒把資料壓棧
            condition.wait()
        # 通知其他執行緒壓棧
        condition.notify()
        # 指標向下移動
        self.pointer -= 1
        data = self.data[self.pointer]
        condition.release()
        # 資料出棧
        return data


# 建立堆疊Stack物件
stack = Stack()


# 生產者執行緒體函式
def producer_thread_body():
    global stack  # 宣告為全域性變數
    # 產生10個數字
    for i in range(0, 10):
        # 把數字壓棧
        stack.push(i)
        # 列印數字
        print('生產:{0}'.format(i))
        # 每產生一個數字執行緒就睡眠
        #time.sleep(1)


# 消費者執行緒體函式
def consumer_thread_body():
    global stack  # 宣告為全域性變數
    # 從堆疊中讀取數字
    for i in range(0, 10):
        # 從堆疊中讀取數字
        x = stack.pop()
        # 列印數字
        print('消費:{0}'.format(x))
        # 每消費一個數字執行緒就睡眠
        #time.sleep(1)


# 主函式
def main():
    # 建立生產者執行緒物件producer
    producer = threading.Thread(target=producer_thread_body)
    # 啟動生產者執行緒
    producer.start()
    # 建立消費者執行緒物件consumer
    consumer = threading.Thread(target=consumer_thread_body)
    # 啟動消費者執行緒
    consumer.start()


if __name__ == '__main__':
    main()