线程死锁浅析

情形1:

dispatch_sync(dispatch_get_main_queue(), ^{
        NSLog(@"不会执行");
    });

如果在主线程添加这段代码,即同步执行添加到主队列的block。这个函数会等block执行完毕返回主线程,再继续执行下面的代码,而block要等主线程返回才会执行,所以循环等待造成死锁。

如果改成异步就可以了,因为当前主线程的一次runloop会马上返回,下一次runloop则会执行主队列里的block。

dispatch_async(dispatch_get_main_queue(), ^{
        NSLog(@"会执行");
    });


还有一个用于在主线程更新ui的方法,如果在主线程执行它,即使是同步的,也并不会造成死锁。

[self performSelectorOnMainThread:@selector(logTest) withObject:nil waitUntilDone:YES];

情形2:

关于operationqueue的。

NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"111");
    }];
    NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"222");
    }];
    NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"333");
    }];
    NSBlockOperation *op4 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"444");
    }];
    NSArray *arr = [NSArray arrayWithObjects:
                    op1,
                    op2,
                    op3,
                    op4,
                    nil];
    [[NSOperationQueue mainQueue]addOperations:arr waitUntilFinished:NO];
    NSLog(@"2");

也是在主线程当中异步执行,所以以上代码会正常运行,并且运行按照顺序,因为主队列是串行队列。

结果:

2015-07-01 14:07:34.064 TestProject[1388:318202] 1
2015-07-01 14:07:34.065 TestProject[1388:318202] 2
2015-07-01 14:07:34.070 TestProject[1388:318202] 111
2015-07-01 14:07:34.071 TestProject[1388:318202] 222
2015-07-01 14:07:34.073 TestProject[1388:318202] 333
2015-07-01 14:07:34.073 TestProject[1388:318202] 444

如果改为同步执行,则会造成死锁:

NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"111");
    }];
    NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"222");
    }];
    NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"333");
    }];
    NSBlockOperation *op4 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"444");
    }];
    NSArray *arr = [NSArray arrayWithObjects:
                    op1,
                    op2,
                    op3,
                    op4,
                    nil];
    [[NSOperationQueue mainQueue]addOperations:arr waitUntilFinished:YES];
    NSLog(@"2");

结果:

2015-07-01 14:10:48.577 TestProject[1423:335286] 1

主队列等待当前的运行循环结束,然后运行队列中的block,而当前运行循环在等待
addOperations 的返回,所以当前运行循环永远不会结束,所以主队列中的block永远不会执行到,程序就这样卡住了。

如果另外创建一个队列(不会是主队列),用同步执行的话:
<pre name="code" class="objc">NSLog(@"1");
    NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"111");
    }];
    NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"222");
    }];
    NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"333");
    }];
    NSBlockOperation *op4 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"444");
    }];
    NSArray *arr = [NSArray arrayWithObjects:
                    op1,
                    op2,
                    op3,
                    op4,
                    nil];
    NSOperationQueue *queue = [[NSOperationQueue alloc]init];//并发,顺序不定
    [queue addOperations:arr waitUntilFinished:YES];
    NSLog(@"2");

运行结果如下:

 
<pre name="code" class="objc">2015-07-01 14:14:44.417 TestProject[1480:353564] 1
2015-07-01 14:14:44.418 TestProject[1480:353689] 111
2015-07-01 14:14:44.418 TestProject[1480:353705] 444
2015-07-01 14:14:44.418 TestProject[1480:353690] 333
2015-07-01 14:14:44.419 TestProject[1480:353685] 222
2015-07-01 14:14:44.419 TestProject[1480:353564] 2

结果正常。因为新创建的队列是可以并发的,所以1,2,3,4的执行顺序不一定。
 
如果改为异步执行,同样正常执行,1,2,3,4block执行顺序不定,但函数会立即返回。
<pre name="code" class="objc">NSLog(@"1");
    NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"111");
    }];
    NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"222");
    }];
    NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"333");
    }];
    NSBlockOperation *op4 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"444");
    }];
    NSArray *arr = [NSArray arrayWithObjects:
                    op1,
                    op2,
                    op3,
                    op4,
                    nil];
    NSOperationQueue *queue = [[NSOperationQueue alloc]init];//并发,顺序不定
    [queue addOperations:arr waitUntilFinished:NO];
    NSLog(@"2");

运行结果:
 
<pre name="code" class="objc">2015-07-01 14:17:53.111 TestProject[1513:365712] 1
2015-07-01 14:17:53.112 TestProject[1513:365712] 2
2015-07-01 14:17:53.112 TestProject[1513:365832] 333
2015-07-01 14:17:53.112 TestProject[1513:365831] 111
2015-07-01 14:17:53.112 TestProject[1513:365837] 444
2015-07-01 14:17:53.113 TestProject[1513:365830] 222

即使主线程阻塞了,1,2,3,4也会正常执行。
 

情形3:
<pre name="code" class="objc">NSLog(@"1");
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        NSLog(@"=================1");
        dispatch_sync(dispatch_get_main_queue(), ^{
            NSLog(@"=================2");
        });
        NSLog(@"=================3");
    });
    NSLog(@"2");
    while (1) {
        
    }
同步执行主队列的block不会执行,因为当前运行循环不会结束。由于是同步的,所以下面的====3也不会执行到。
 
运行结果:
<pre name="code" class="objc">2015-07-01 14:21:25.499 TestProject[1651:389143] 1
2015-07-01 14:21:25.499 TestProject[1651:389143] 2
2015-07-01 14:21:25.499 TestProject[1651:389172] =================1
如果改为异步在主线程执行,则====3会执行。
 
<pre name="code" class="objc">NSLog(@"1");
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        NSLog(@"=================1");
        dispatch_async(dispatch_get_main_queue(), ^{
            NSLog(@"=================2");
        });
        NSLog(@"=================3");
    });
    NSLog(@"2");
    while (1) {
        
    }
结果:
 
<pre name="code" class="objc">2015-07-01 14:24:54.855 TestProject[1687:402116] 1
2015-07-01 14:24:54.855 TestProject[1687:402116] 2
2015-07-01 14:24:54.855 TestProject[1687:402152] =================1
2015-07-01 14:24:54.855 TestProject[1687:402152] =================3

总结:
 
在主线程中不要同步执行在主队列中的block。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值