python threading模块、Condition类讲解

16.2.4. Condition Objects

def Condition(*args, **kwargs):
    """Factory function that returns a new condition variable object.

    A condition variable allows one or more threads to wait until they are
    notified by another thread.

    If the lock argument is given and not None, it must be a Lock or RLock
    object, and it is used as the underlying lock. Otherwise, a new RLock object
    is created and used as the underlying lock.

    """

A condition variable is always associated with some kind of lock; this can be passed in or one will be created by default. (Passing one in is useful when several condition variables must share the same lock.)

A condition variable has acquire() and release() methods that call the corresponding methods of the associated lock. It also has a wait() method, and notify() and notifyAll() methods. These three must only be called when the calling thread has acquired the lock, otherwise a RuntimeError is raised.

The wait() method releases the lock, and then blocks until it is awakened by a notify() or notifyAll() call for the same condition variable in another thread. Once awakened, it re-acquires the lock and returns. It is also possible to specify a timeout.

The notify() method wakes up one of the threads waiting for the condition variable, if any are waiting. The notifyAll() method wakes up all threads waiting for the condition variable.

Note: the notify() and notifyAll() methods don’t release the lock; this means that the thread or threads awakened will not return from their wait() call immediately, but only when the thread that called notify() or notifyAll() finally relinquishes ownership of the lock.
翻译:notify和notifyAll方法并没有释放锁,而是仅仅唤醒那些等待的线程,只有当调用notify和notifyAll的线程真正释放锁时(调用release方法),那些等待的线程才可以从wait方法中返回,进行往下执行。

Tip: the typical programming style using condition variables uses the lock to synchronize access to some shared state; threads that are interested in a particular change of state call wait() repeatedly until they see the desired state, while threads that modify the state call notify() or notifyAll() when they change the state in such a way that it could possibly be a desired state for one of the waiters. For example, the following code is a generic producer-consumer situation with unlimited buffer capacity:

# Consume one item
cv.acquire() #获取锁
while not an_item_is_available():
    cv.wait() #释放锁,等待唤醒通知,然后获取锁
get_an_available_item()
cv.release() #释放锁

# Produce one item
cv.acquire() #获取锁
make_an_item_available()
cv.notify() #唤醒等待线程
cv.release() #释放锁

To choose between notify() and notifyAll(), consider whether one state change can be interesting for only one or several waiting threads. E.g. in a typical producer-consumer situation, adding one item to the buffer only needs to wake up one consumer thread.

用大白话说一下这个Condition的作用,以及有了Lock/RLock后,为什么还需要Condition.

  1. Lock/RLock是互斥锁,主要作用是并行访问共享资源时,保护共享资源,防止出现脏数据。
  2. Condition依赖于Lock/RLock,主要是使用了Lock/RLock的阻塞特性,同时Condition自身提供了wait/notify/notifyAll方法,用于通知其他并行线程,可以访问共享资源了。可以这么理解,Condition提供了一种多线程通信机制,线程1需要数据,那么线程1就阻塞等待,这是线程2就去制造数据,线程2制造好数据后,通知线程1可以去取数据了,然后线程1去获取数据。

演示:使用Condition实现生产者/消费者模型。

# coding:gbk

import threading
import time

cv=threading.Condition()

product=0

def an_item_is_available():
    global product
    if not product:
        return False
    else:
        return True

def get_an_available_item():
    global product
    product-=1
    return '消费了一个产品。。。\n'.decode('gbk')

def make_an_item_available():
    global product
    product+=1
    return '生产了一个产品。。。\n'.decode('gbk')

def consume():
    global cv

    while True:
        cv.acquire()

        while not an_item_is_available():
            cv.wait()

        print get_an_available_item()

        cv.release()

def produce():
    global cv

    while True:
        cv.acquire()

        print make_an_item_available()


        cv.notify()

        cv.release()

        time.sleep(1)

if __name__ == '__main__':
    t1=threading.Thread(target=produce,args=())
    t2=threading.Thread(target=consume,args=())

    t2.start()

    time.sleep(10)

    t1.start()

运行结果:

C:\Python27\python.exe E:/pythonproj/基础练习/t6.py
生产了一个产品。。。

消费了一个产品。。。

生产了一个产品。。。

消费了一个产品。。。


Process finished with exit code 1
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

历史五千年

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值