多线程

创建线程

import time
import threading


class MyThread(threading.Thread):
    def run(self):
        for i in range(5):
            print('thread {},@number:{}'.format(self.name, i))
            time.sleep(1)


if __name__ == '__main__':
    threads = [MyThread() for i in range(3)]
    for t in threads:
        t.start()

线程同步与互斥锁

  给资源进行加锁,也就是访问资源的线程需要获得锁才能访问

lock = threading.Lock()

  在线程中获取锁

lock.acquire()

  需要释放锁

lock.release()

  Python 提供可重入锁(RLock)。RLock 内部维护着一个 Lock 和一个 counter 变量,counter 记录了 acquire 的次数,从而使得资源可以被多次 require。直到一个线程所有的 acquire 都被 release,其他的线程才能获得资源

r_lock = threading.RLock()

Condition 条件变量

  使用 Condition 对象可以在某些事件触发或者达到特定的条件后才处理数据,Condition 除了具有 Lock 对象的 acquire 方法和 release 方法外,还提供了 wait 和 notify 方法

  线程首先 acquire 一个条件变量锁。如果条件不足,则该线程 wait,如果满足就执行线程,甚至可以 notify 其他线程。其他处于 wait 状态的线程接到通知后会重新判断条件。

  在线购物买家和卖家的示例

import time
import threading


class Consumer(threading.Thread):
    def __init__(self, cond, name):
        # 初始化
        super(Consumer, self).__init__()
        self.cond = cond
        self.name = name

    def run(self):
        # 确保先运行Seeker中的方法
        time.sleep(1)
        self.cond.acquire()
        print(self.name + ': 我这两件商品一起买,可以便宜点吗')
        self.cond.notify()
        self.cond.wait()
        print(self.name + ': 我已经提交订单了,你修改下价格')
        self.cond.notify()
        self.cond.wait()
        print(self.name + ': 收到,我支付成功了')
        self.cond.notify()
        self.cond.release()
        print(self.name + ': 等待收货')


class Producer(threading.Thread):
    def __init__(self, cond, name):
        super(Producer, self).__init__()
        self.cond = cond
        self.name = name

    def run(self):
        self.cond.acquire()
        # 释放对琐的占用,同时线程挂起在这里,直到被 notify 并重新占有琐。
        self.cond.wait()
        print(self.name + ': 可以的,你提交订单吧')
        self.cond.notify()
        self.cond.wait()
        print(self.name + ': 好了,已经修改了')
        self.cond.notify()
        self.cond.wait()
        print(self.name + ': 嗯,收款成功,马上给你发货')
        self.cond.release()
        print(self.name + ': 发货商品')


cond = threading.Condition()
consumer = Consumer(cond, '买家')
producer = Producer(cond, '卖家')
consumer.start()
producer.start()

线程间通信

  从一个线程向另一个线程发送数据最安全的方式可能就是使用 queue 库中的队列了。创建一个被多个线程共享的 Queue 对象,这些线程通过使用 put() 和 get() 操作来向队列中添加或者删除元素。

from queue import Queue
from threading import Thread


def write(q):
    for value in ['a', 'b', 'c']:
        q.put(value)


def read(q):
    while True:
        value = q.get(True)
        print("Queue取出数据:{0}".format(value))


if __name__ == '__main__':
    q = Queue()
    t1 = Thread(target=write, args=(q,))
    t2 = Thread(target=read, args=(q,))
    t1.start()
    t2.start()

  Python 还提供了 Event 对象用于线程间通信,是由线程设置的信号标志,如果信号标志位真,则其他线程等待直到信号接触。

  Event 对象实现了简单的线程通信机制,提供了设置信号,清楚信号,等待等用于实现线程间的通信。

  • 设置信号

  使用 Event 的 set() 方法可以设置 Event 对象内部的信号标志为真。Event 对象提供了 isSet() 方法来判断其内部信号标志的状态。当使用 event 对象的 set() 方法后,isSet() 方法返回真

  • 清除信号

  使用 Event 对象的 clear() 方法可以清除 Event 对象内部的信号标志,即将其设为假,当使用 Event 的 clear 方法后,isSet() 方法返回假

  • 等待

  Event 对象 wait 的方法只有在内部信号为真的时候才会很快的执行并完成返回。当 Event 对象的内部信号标志位假时,则 wait 方法一直等待到其为真时才返回。

 

posted on 2022-05-11 23:17  溪水静幽  阅读(21)  评论(0)    收藏  举报