GCD与Operation多线程总结

总结一下多线程应用中的一些内容吧,好记性不如烂笔头

线程同步

GCD中 多线程开发中能线程同步(数据竞态处理)的方式有如下5种:

  • 串行队列(Serial Queue)

  • 并发队列的 dispatch_barrier_async(栅栏函数)

  • dispatch_semaphore(信号量)

    信号量也可以指定最多有多少个线程执行任务

  • Dispatch Group

  • dispatch_set_target_queue(平时用得少,以后研究)

Operation 中线程同步有点类似与 GCD 中的 Dispatch Group 的处理方式: 

  • BlockOperation 中添加任务后,调用 completeBlock可以线程同步,功能与 Dispatch Group 一样

    let blockOperation = BlockOperation()
    blockOperation.addExecutionBlock {
    print("任务1")
    }
    blockOperation.addExecutionBlock {
    print("任务2")
    }
    blockOperation.addExecutionBlock {
    print("任务3")
    }
    blockOperation.addExecutionBlock {
    print("任务4")
    }
    blockOperation.completionBlock = {
    print("全部执行完成后执行的任务")
    }
    blockOperation.start()
  • OperationQueue 添加Operation 后,调用waitUntilAllOperationsAreFinished() 可以做到线程同步,等待队列中所有 Operation 都执行完之后再继续向下执行代码。

    let operationQueue = OperationQueue()
    /// 设置最大并发线程数
    operationQueue.maxConcurrentOperationCount = 2
    operationQueue.addOperation {
    print("任务2")
    }
    operationQueue.addOperation {
    sleep(2)
    print("任务3")
    }
    operationQueue.addOperation {
    print("任务4")
    }
    operationQueue.addOperation {
    print("任务5")
    }
    operationQueue.addOperation {
    print("任务6")
    }
    /// 等待所有任务操作完成
    operationQueue.waitUntilAllOperationsAreFinished()
    print("主任务")

限制线程执行个数(最多能执行的线程数)

  • GCD 中可以通过 信号量: dispatch_semaphore 来处理,在它创建时指定线程个数

  • Operation 中可以通过 OperationQueue类的使用,指定给类中的 maxConcurrentOperationCount 来指定线程个数

线程死锁问题(GCD为例)

  • 在主线程中调用同步操作

    因为主线程本身是一个串行队列,因此执行任务过程是按先进先出,只有前面的任务执行完了才会执行后面的任务。而在主线程中调用同步操作,就是变成主线程等待同步操作完成,而同步操作等待主线程前的任务完成,而此时主线程正在执行该线程同步任务,因此变成了互相等待完成,也就永远不会完成了,变成线程死锁.

    DispatchQueue.main.sync {
    print("主线程调用线程同步")
    }
    输出:
    在 Swift环境,直接编译报错了
  • 串行队列异步嵌套同步、串行队列同步嵌套同步

    同理,串行队列异步嵌套同步、串行队列同步嵌套同步都会造成线程死锁的问题

    串行队列异步嵌套同步:

    let serialQueue = DispatchQueue(label: "serial.queue")
    serialQueue.async {
    print("异步任务")
    serialQueue.sync {
    print("同步任务")
    }
    }

    以上代码输出:异步任务,线程被卡在嵌套的线程同步的地方

    串行队列同步嵌套同步: 以下代码输出:同步任务1,线程被卡在嵌套的线程同步的地方

    let serialQueue = DispatchQueue(label: "serial.queue")
    serialQueue.sync {
    print("同步任务1")
    serialQueue.sync {
    print("同步任务2")
    }
    }

而对于并发队列来说,不管是同步嵌套异步,还是异步嵌套同步,都是没问题的


原文始发于微信公众号(三万之一):GCD与Operation多线程总结

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/231212.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!