Xcode 10.2 & Swift 5.0 - semaphore 信号量

import Cocoa

/// 信号量对象
class DispatchSemaphore {

    /// 创建一个信号量, 并设置初始值
    /// - Parameters:
    ///   - value: 信号量的初始值。必须>=0,否则会返回NULL。
    /// - Returns: 信号量对象
    init(value: Int) 
    
    /// 发送信号量。该函数会对信号量的值进行+1操作。
    /// - Returns:
    ///   - 当返回值=0时,表示当前不存在线程因为wait而阻塞。
    ///   - 当返回值>0时,表示其当前有(一个或多个)线程因为wait而阻塞,并且唤醒一个等待的线程(当线程有优先级时,唤醒优先级最高的线程;否则随机唤醒)。
    func signal() -> Int 

    /// 等待信号量。该函数会对信号量的值进行-1操作。这个函数的作用是这样:
    ///   如果信号量的值>0,该函数所处线程就继续执行下面的语句,并且将信号量的值-1;
    ///   如果信号量的值=0,那么这个函数就阻塞当前线程等待timeout,
    ///     如果等待期间信号量的值被signal函数+1了,且该函数(即dispatch_semaphore_wait)所处线程获得了信号量,那么就继续向下执行并将信号量-1。
    ///     如果等待期间没有获取到信号量或者信号量的值一直为0,那么等到timeout时,其所处线程自动执行其后语句。
    func wait() 

    /// 等待信号量。可以设置等待超时时间
    /// - Parameters:
    ///   - timeout: DispatchTime为主板时间CPU时钟计时
    /// - Returns:
    ///   - 当返回值=DispatchTimeoutResult.success时,表示在timeout之前,该函数所处的线程被成功唤醒。
    ///   - 当返回值=DispatchTimeoutResult.timedOut时,表示timeout发生。
    func wait(timeout: DispatchTime) -> DispatchTimeoutResult 
    
    /// 等待信号量。可以设置等待超时时间
    /// - Parameters:
    ///   - timeout: DispatchWallTime为实际时间即系统时间
    /// - Returns:
    ///   - 当返回值=DispatchTimeoutResult.success时,表示在timeout之前,该函数所处的线程被成功唤醒。
    ///   - 当返回值=DispatchTimeoutResult.timedOut时,表示timeout发生。
    func wait(wallTimeout: DispatchWallTime) -> DispatchTimeoutResult 
}

/// 场景1: 将异步函数调整为同步, 因为wait的存在, 能够保证'step 5'一定能在'step 2'之后执行, 整个程序看上去像是顺序执行了。
/// 本场景中, 程序执行到wait时, 由于当前信号量为0, 会阻塞当前线程。
/// 此时global线程仍在并行执行, 它会等待2秒后, 执行signal让信号量加1。
/// 由于检测到有处于wait状态的线程(主线程), 于是将这个线程唤起, 这就造成了有两个线程同时执行, 作为结果的'step 3'和'step 5'的输出顺序不定。
func example1() {
    let semaphore = DispatchSemaphore(value: 0)
    print("step 1")
    DispatchQueue.global().async {
        sleep(2)
        print("step 2")
        semaphore.signal()
        print("step 3")
    }
    print("step 4")
    semaphore.wait()
    print("step 5")
}
//example1()

/// 场景2: 线程锁, wait与signal构成了加锁和解锁的要素, 这对函数之间的代码会被保护起来, 不会同时执行。
/// 本场景中, 两个global线程并行执行, 因此'step 10'和'step 20'的输出顺序不定。注意: 先执行'step'的线程, 不一定会先执行wait。
/// 先到达wait的线程, 由于当前信号量为1, 因此可以顺利执行下去, 顺便会将信号量减1。
/// 后到达wait的线程, 由于当前信号量为0, 会阻塞当前线程(后到线程)。
/// 当先线程执行signal后, 会令信号量加1, 于是唤起了后到线程, 后到线程的阻塞状态解除。
func example2() {
    
    let semaphore = DispatchSemaphore(value: 1)
    print("step 00")
    
    DispatchQueue.global().async {
        sleep(2)
        print("step 10")
        semaphore.wait()
        print("step 11")
        sleep(2)
        print("step 12")
        semaphore.signal()
        print("step 13")
    }
    
    DispatchQueue.global().async {
        sleep(2)
        print("step 20")
        semaphore.wait()
        print("step 21")
        sleep(2)
        print("step 22")
        semaphore.signal()
        print("step 23")
    }
    
    print("step 01")
}
//example2()

 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值