有序打印

有序打印:
        给定一个类
        class  Foo():
                def  first():
                        print("first",  end="  ")
                def  second():
                        print("second",  end="  ")
                def  third():
                        print("third",  end="  ")
        建立实例化对象,建立3个线程,此时3个线程都共享这个对象,
        让3个线程分别运行  first(),  second(),  third(),  需要确保  first  second  third  的打印顺序

方法一;
        线程锁
                一个线程在代码的某处使用线程锁后(acquire),在这个锁释放前(release),其它线程都不能再使用这个锁。
                场景一:用线程锁,包含某段代码,这样每次就只会有一个线程执行这段代码
                场景二:在代码A处使用了线程锁  lock1,在代码B处也使用了  lock1。
                              假设线程  t1  先执行到代码A处(lock1开启了),  在代码块还没执行完时(lock1还未释放),
                              线程  t2  执行到代码B处,此时就会请求开启  lock1,  但由于  lock1在线程t1还未释放,
                              由此线程t2就会阻塞在这里,等待线程t1释放  lock1
        此题类似场景二,  打印  first  和  second  处可以使用相同的线程锁,这样就可以确保在打印完一个后才能打印另外一个。
        因此问题转变成  “怎么让打印first的线程,第一个获取线程锁?”,
        可以换一个思路  “在所有线程运行前,就开启线程锁,在打印完first后,才释放这个锁”  这样即使打印  second  的线程
        先运行,由于线程锁还未释放,不会重新开启锁,也就不会先打印  second

from threading import Lock, Thread


class Foo:
    def __init__(self):
        self.first_lock = Lock()
        self.second_lock = Lock()
        self.first_lock.acquire()
        self.second_lock.acquire()

    def first(self, print_first: 'Callable[[], None]') -> None:
        # printFirst() outputs "first".
        print_first()
        # Notify the thread that is waiting for the first job to be done.
        self.first_lock.release()

    def second(self, print_second: 'Callable[[], None]') -> None:
        # Wait for the first job to be done
        self.first_lock.acquire()
        # print_second() outputs "second".
        print_second()
        # Notify the thread that is waiting for the second job to be done.
        self.second_lock.release()
        self.first_lock.release()

    def third(self, print_third: 'Callable[[], None]') -> None:
        # Wait for the second job to be done.
        with self.second_lock:
            # print_third() outputs "third".
            print_third()


def print_first():
    print("first", end=" ")


def print_second():
    print("second", end=" ")


def print_third():
    print("third", end=" ")


if __name__ == '__main__':
    foo = Foo()
    t1 = Thread(target=foo.first, args=[print_first])
    t2 = Thread(target=foo.second, args=[print_second])
    t3 = Thread(target=foo.third, args=[print_third])
    t3.start()
    t2.start()
    t1.start()