GCD队列与线程的思考

首先声明2个串行队列A,B

-(void)viewDidLoad 
{    
    [super viewDidLoad];
    //初始化串行队列A,B
    A = dispatch_queue_create("A", DISPATCH_QUEUE_SERIAL);

    B = dispatch_queue_create("B", DISPATCH_QUEUE_SERIAL);

    test1();
}

void test1()
{
    dispatch_async(A, ^{
        test2();    //任务T1
    });
    NSLog(@"test1 called");
}

void test2()
{
    dispatch_sync(B, ^{
        test3();    //任务T2
    });
    NSLog(@"test2 called");
}

void test3()
{
    dispatch_sync(A, ^{
        int a = 3;   //任务T3
    });
    NSLog(@"test3 called");
}

运行程序后,结果为:
111111111

只输出了“test1 called”,为什么?

从头分析下这段代码,在test1,test2,test3函数里面分别加断点如下所示:

2222222222

3333333

33333333

33333

调试过程中,test3中的block不会进入,原因在于test2与test3中的两个block导致的死锁。

程序运行到test1时,向队列A异步派发一个block任务T1,所以test1中不等待dispatch_async()函数返回就继续向下执行,输出”test1 called”。

当执行队列A中的block任务T1时,调用test2函数,向队列B中同步派发一个任务T2,等待B中的任务T2执行完再向下执行,B中的任务是调用test3函数,继续向A中分派一个任务T3,等待T3执行完再向下执行,而串行队列中的任务是先进先出,此时队列A中已经有一个任务T1在执行,必须等待T1执行完,T3才能开始执行;而T1要等待T2执行完,T2要等待T3执行完,T3要等待T1执行完,所以造成死锁。

为什么只打印”test1 called”的原因,我们找到了,但还有一点我比较疑惑的事情,任务T1,T2是在哪个线程里面执行的,在断点调试截图中我们看到,只有在执行任务T1时才创建了一个线程Thread6,执行T2时也是在Thread6中。

从调试截图中我们猜测只有用dispatch_async()函数分派block任务时会创建一个新的线程,而用dispatch_sync()函数分派block任务并不会创建线程,block执行时与dispatch_sync()函数处于同一个线程中。

说的比较绕,参考了下别人的说法,dispatch_sync所派发的block的执行线程和dispatch_sync上下文线程是同一个线程。

对于dispatch_sync中的block执行线程问题请参考:
http://zhangbuhuai.com/2015/04/11/%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3dispatch_sync/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值