python标准库threading源码解读【二】

转载至我的知乎文章:https://zhuanlan.zhihu.com/p/93024096
紧接上一篇文章:https://www.jianshu.com/p/5a488fab56cb

分割线

目录

1.Event的介绍和用法

2.Event源码解析

分割线
1.Event的介绍和用法

可以参考下:
https://cloud.tencent.com/developer/article/1328495
Event中的锁通过Condition实现,用到了类Condition中的wait()和notify_all()方法。
Event提供了一个信号标志flag,利用flag的状态就可以实现线程之间的相互依赖;包含wait(),clear(),set(),is_set()方法和私有方法_reset_internal_locks()。

is_set() 获取event的设置值,默认为False
set() 设置event的值为True
clear() 设置event的值为False
wait() 等到event的值被设为True就执行

# 代码来自上述链接
import threading
import time

def traffic_light(event):
    count = 0
    event.set()
    while True:
        # 如果计数器[0, 5)之间, 红灯,event=False
        if 0 <= count < 5:
            event.clear()
            print("light is Red")
        # 如果计数器[5, 10)之间, 绿灯,event=True
        elif 5 <= count < 10:
            event.set()
            print("light is Green")
        # 如果计数器大于10,红灯,将event设置为False,计数器置为0
        else:
            event.clear()
            count = 0
        time.sleep(1)
        count += 1

def car(name, event):
    while True:
        if not event.is_set():
            # event为False, 表示红灯, 车只能等待
            print("RED, the %s is waiting..." % name)
            # 此处会阻塞住,直到event被设置为True在执行
            event.wait()
            print("Green, The %s going...." % name)

e = threading.Event()
light = threading.Thread(target=traffic_light, args=(e,))
light.start()
car1 = threading.Thread(target=car, args=("Tesla", e, ))
car1.start()

线程car在输出“RED。。。。。。”之后会在wait()中一直等待,直到event的信号标志量为True;
线程light在0-5时,只会调用event.clear(),event的信号标志量一直为False;线程car没有动静;
线程light在6-10时,只会调用event.set(),event的信号标志量一直为True;线程car可以被调用;
实现了线程car对线程light的依赖。

2.Event源码解析

直接看源码

源码 1/3
class Event:
    def __init__(self):
        self._cond = Condition(Lock())
        self._flag = False

    def _reset_internal_locks(self):
        # private!  called by Thread._reset_internal_locks by _after_fork()
        self._cond.__init__(Lock())

    def is_set(self):
        """Return true if and only if the internal flag is true."""
        return self._flag

    isSet = is_set

def init(self):
定义condition锁和标志量flag
def _reset_internal_locks(self):
好像是线程异常退出的时候,重新设置线程锁condition的东西,后面写到了再学习学习;
def is_set(self):
这个简单,返回flag状态;

源码 2/3
    def set(self):
        """Set the internal flag to true.

        All threads waiting for it to become true are awakened. Threads
        that call wait() once the flag is true will not block at all.

        """
        with self._cond:
            self._flag = True
            self._cond.notify_all()

    def clear(self):
        """Reset the internal flag to false.

        Subsequently, threads calling wait() will block until set() is called to
        set the internal flag to true again.

        """
        with self._cond:
            self._flag = False

【注释我都不想删掉了,凑点字数23333】
def set(self):
flag首先设为True,继而释放所有线程
def clear(self):
flag设为False

源码 3/3
    def wait(self, timeout=None):
        """Block until the internal flag is true.

        If the internal flag is true on entry, return immediately. Otherwise,
        block until another thread calls set() to set the flag to true, or until
        the optional timeout occurs.

        When the timeout argument is present and not None, it should be a
        floating point number specifying a timeout for the operation in seconds
        (or fractions thereof).

        This method returns the internal flag on exit, so it will always return
        True except if a timeout is given and the operation times out.

      """
        with self._cond:
            signaled = self._flag
            if not signaled:
                signaled = self._cond.wait(timeout)
            return signaled

def wait(self, timeout=None):
先判断flag信号,只有当前状态下flag是False才会进行等待,并且释放condition一级锁(也就是实例化Event类中定义的 self._cond = Condition(Lock()) )
Event.wait()函数在被Event.set()函数唤醒之后,在类condition的wait()函数中的finally尝试恢复一级锁;set()函数在下一句代码中才会释放锁;释放之后难道一定会是finally中的语句拿到嘛?不过我倒是感觉谁拿到这个所都无所谓。。。
END

你可能感兴趣的:(python标准库threading源码解读【二】)