码迷,mamicode.com
首页 > 编程语言 > 详细

线程死锁浅析

时间:2015-07-01 18:35:41      阅读:164      评论:0      收藏:0      [点我收藏+]

标签:

情形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。

版权声明:本文为博主原创文章,未经博主允许不得转载。

线程死锁浅析

标签:

原文地址:http://blog.csdn.net/ioszhuang2015/article/details/46698503

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!