简单易懂的DispatchSemaphore

作者: 是的蛮大人 | 来源:发表于2017-07-28 18:16 被阅读583次

DispatchSemaphore

信号量,一种用来控制并发访问资源的机制,多用于多线程中,可以控制并发线程数量。

例子

  • 第一个例子
let queue = DispatchQueue.global()
var arr = [Int]()
for i in 0..<10000 {
    queue.async {
        print("add \(i)")
        arr.append(i)
    }
}

运行结果:运行一定时间后,程序crash
crash原因分析:Array不是线程安全的,多线程并发操作Array导致crash

  • 第二个例子
let semaphore = DispatchSemaphore(value: 1)
let queue = DispatchQueue.global()
var arr = [Int]()
for i in 0..<10000 {
    queue.async {
        if semaphore.wait(timeout: .distantFuture) == .success {
            print("add \(i)")
            arr.append(i)
            semaphore.signal()
        }
    }
}

运行结果:运行正常,数据被成功添加到arr
注意:arr中的数据并不是严格按照0~9999这个顺序添加进去的

例子解析

  • 创建信号量
let semaphore = DispatchSemaphore(value: 1)

value表示的是初始值,我们这里设置为1
另一种解释:WC里只有一个坑

  • 等待信号量
if semaphore.wait(timeout: .distantFuture) == .success

如果semaphore的值不为0,上面函数返回success,同时会将semaphore的值减1;
如果是0,则线程一直等待(函数不返回,下面的代码不会执行),直到timeout

timeout可以控制可等待的最长时间,设置为.distantFuture表示永久等待

另一种解释:来了一个客人,如果有坑,则占了,坑数-1,否则等待上一个客人用完离开

  • 发送信号量
semaphore.signal()

semaphore的值+1,这个时候其他等待中的线程就会被唤醒执行(同等优先级下随机唤醒
另一种解释:客人用完离开了,坑数+1

总结一下

  • 代码设置了信号量的初始值是1
  • 第一次循环,wait返回success,执行if语句内的代码,同时信号量减一变为0
    更严格的说是queue中的异步task第一个被执行时,因为第一个task不一定是第一次循环添加的那个
  • 第二次循环,因为信号量为0,所以线程等待(假设第一次循环if内的代码还没执行完),后面的循环类似
  • 当第一次循环if语句内的semaphore.signal()代码执行后,信号量的值加1,变为1。所以当前正在等待的线程中的某一个被唤醒并执行,其他的线程继续等待
  • 依次类推...

以上,如有问题,欢迎指正,感激不尽...

相关文章

  • 简单易懂的DispatchSemaphore

    DispatchSemaphore 信号量,一种用来控制并发访问资源的机制,多用于多线程中,可以控制并发线程数量。...

  • DispatchSemaphore & DispatchGrou

    标记 DispatchSemaphore DispatchGroup

  • 多线程

    异步网络请求串行 DispatchSemaphore初始值为1 DispatchSemaphore初始值为0还是1...

  • DispatchSemaphore

    /// 信号量对象class DispatchSemaphore { }参考: https://blog.csdn...

  • Swift DispatchSemaphore

    信号量机制实质是PV操作,具体操作如下: 1、P操作的动作是: (1)S减1; (2)若S减1后大于或等于零,则程...

  • 【转】DispatchSemaphore

    ————————————————版权声明:本文为CSDN博主「vision66」的原创文章,遵循 CC 4.0 B...

  • iOS 信号量semaphore学习总结

    常用API: let semaphore = DispatchSemaphore.init(value: 1)//...

  • 简单易懂的udp

    实现简单的udp请求服务模式 udp 是一种简单传输协议,实现简单,占用系统资源少 运行结果 服务端代码 客户端代...

  • 简单易懂的Redux

    简单易懂的Redux 根据redux官方文档来说,可以将redux分为三个核心部分。 actions reduce...

  • 简单易懂的 KNN

    KNN 在机器学习中,我们通过训练数据来学习出一个模型,通常我们是先设计模型(Model),通过学习得到模型最优参...

网友评论

  • DesmondDAI:感谢楼主分享~
    不过有个地方想指正,就是第一个例子的 crash 不是因为线程安全问题,是 closure 没有对变量 i 捕获(capture),导致在 concurrent 运行中,用完的 i 指针被二次释放,因为 crash 时系统抛出的错误是:`error for object 0x10a08d168: pointer being freed was not allocated`
    是的蛮大人:谢谢你的补充:smile:

本文标题:简单易懂的DispatchSemaphore

本文链接:https://www.haomeiwen.com/subject/qplflxtx.html