• 多线程--信号对象(Semaphore)


    Semaphore工作原理:

    Semaphore对象支持上下文管理协议。
    Semaphore对象内部管理一个计数器,并有两个方法对计数器工作:
    1.acquire(blocking=True, timeout=None)
    2.release()
    该计数器由每个acquire()调用递减,并由每个release()调用递增。计数器永远不会低于零,当acquire()发现计数器为零时,线程阻塞,等待其他线程调用release()

     当blocking=True时:如果调用时计数器大于零,则将其减1并立即返回。如果在调用时计数器为零,则阻塞并等待,直到其他线程调用release()使其大于零。因此如果多个acquire() 被阻塞,release()将只唤醒其中一个,这个过程会随机选择一个,因此不应该依赖阻塞线程的被唤醒顺序。

    计算方式:release()调用数减去acquire()调用数加一个初始值的计数器
    demo: 两个不同的线程将会共用一个 FooBar 实例。其中一个线程将会调用 foo() 方法,另一个线程将会调用 bar() 方法。

    输入: n = 1
    输出: "foobar"
    解释: 这里有两个线程被异步启动。其中一个调用 foo() 方法, 另一个调用 bar() 方法,"foobar" 将被输出一次。

    思路:信号交替,调用acquire()则+1 ,调用release()则 -1

     1 import threading
     2 
     3 
     4 class FooBar:
     5     def __init__(self, n):
     6         self.n = n
     7         self.demotex1 = threading.Semaphore(1) 
     8         self.demotex2 = threading.Semaphore(0)
     9         
    10 
    11     def foo(self, printFoo: 'Callable[[], None]') -> None:
    12         
    13         for i in range(self.n):
    14             self.demotex1.acquire()  # -1 
    15             # printFoo() outputs "foo". Do not change or remove this line.
    16             printFoo()
    17             self.demotex2.release()  # +1  释放信号,使计数器递增1。当计数器为零并有另一个线程等待计数器大于零时,唤醒该线程。
    18             
    19 
    20 
    21     def bar(self, printBar: 'Callable[[], None]') -> None:
    22         
    23         for i in range(self.n):
    24             self.demotex2.acquire() 
    25             # printBar() outputs "bar". Do not change or remove this line.
    26             printBar()
    27             self.demotex1.release()

    该题来自力扣

  • 相关阅读:
    .Net -- NLog日志框架配置与使用
    Prism -- 简介
    Prism.WPF -- Prism框架使用(下)
    Prism.WPF -- Prism框架使用(上)
    Win32Api -- 关闭当前应用
    WPF -- 一种圆形识别方案
    C#语言特性及发展史
    WPF -- 一种实现本地化的方法
    DEV中右键菜单如何只在非空单元格上显示?
    打开一个窗体,其他窗体处于不可编辑状态
  • 原文地址:https://www.cnblogs.com/leisunny/p/13470367.html
Copyright © 2020-2023  润新知