zoukankan      html  css  js  c++  java
  • GCD 之线程死锁

    GCD 确实好用 ,很强大,相比NSOpretion 无法提供 取消任务的功能。

    如此强大的工具用不好可能会出现线程死锁。 如下代码:

    - (void)viewDidLoad
    {
        [super viewDidLoad];
        NSLog(@"=================4");
        dispatch_sync(dispatch_get_main_queue(), ^{
            NSLog(@"=================5");
        });
        NSLog(@"=================6");
    }

    GCD Queue 分为三种:

    1,The main queue  :主队列,主线程就是在个队列中。

    2,Global queues : 全局并发队列。

    3,用户队列:是用函数 dispatch_queue_create 创建的自定义队列

    dispatch_sync 和  dispatch_async 区别:

    dispatch_async(queue,block)  async 异步队列,dispatch_async 函数会立即返回, block会在后台异步执行。

    dispatch_sync(queue,block)   sync 同步队列,dispatch_sync 函数不会立即返回,及阻塞当前线程,等待 block同步执行完成。

    分析上面代码:

    viewDidLoad 在主线程中, 及在
    dispatch_get_main_queue() 中,执行到sync 时 向
    dispatch_get_main_queue()插入 同步 threed1.

    sync 会等到 后面block 执行完成才返回, sync 又再 dispatch_get_main_queue() 队列中,
    它是串行队列,sync 是后加入的,前一个是主线程,
    所以 sync 想执行 block 必须等待主线程执行完成,主线程等待 sync 返回,去执行后续内容。

    照成死锁,sync 等待mainThread 执行完成, mianThread 等待sync 函数返回。

    下面例子:
    - (void)viewDidLoad
    {
        [super viewDidLoad];
    
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
        
        NSLog(@"=================1");
        
        dispatch_sync(dispatch_get_main_queue(), ^{
            NSLog(@"=================2");
    
        });
        NSLog(@"=================3");
    
        
    });
    
    }

    程序会完成执行,为什么不会出现死锁。

    首先: async 在主线程中  创建了一个异步线程 加入  全局并发队列,async 不会等待block 执行完成,立即返回,

    1,async 立即返回, viewDidLoad 执行完毕,及主线程执行完毕。 
    2,同时,全局并发队列立即执行异步 block , 打印 1, 当执行到 sync 它会等待 block 执行完成才返回, 及等待
    dispatch_get_main_queue() 队列中的 mianThread 执行完成, 然后才开始调用block 。

    因为1 和 2 几乎同时执行,因为2 在全局并发队列上, 2 中执行到sync 时 1 可能已经执行完成或 等了一会,mainThread 很快退出, 2 等已执行后续内容。

    如果阻塞了主线程,2 中的sync 就无法执行啦,mainThread 永远不会退出, sync 就永远等待着,

    - (void)viewDidLoad
    {
        [super viewDidLoad];
    dispatch_async(dispatch_get_global_queue(
    0, 0), ^{ NSLog(@"=================1"); dispatch_sync(dispatch_get_main_queue(), ^{ NSLog(@"=================2"); }); NSLog(@"=================3"); }); NSLog(@"==========阻塞主线程"); while (1) { } NSLog(@"========2==阻塞主线程"); }

    打印如下:

    2014-11-30 17:56:22.296 Test[6108:379350] =================1

    2014-11-30 17:56:22.296 Test[6108:379231] ==========阻塞主线程

    永远等着。。。。。

     

    知道原理以后就会减少出错啦。





  • 相关阅读:
    修改Tomcat的端口号方法
    Java与数据库对应的日期类型
    解决ora-00054 Oracle锁表问题
    qemu+gdb调试内核出现remote ‘g’ packet reply is too long
    构建调试Linux内核网络代码的环境MenuOS系统
    c语言实现简单的hello/hi聊天程序
    traceroute命令研究报告
    c++对象初始化中各构造器的顺序
    嵌入式面试题(1)
    Android驱动笔记(8)——bugreport介绍
  • 原文地址:https://www.cnblogs.com/DamonTang/p/4133481.html
Copyright © 2011-2022 走看看