造成线程锁死的几种情况

主队列添加剂同步任务


原因:对于主队列无论是同步异步都不会创建线程,而且主队列中的任务只有在主线程空闲的时候才会执行.如果是主队列同步会造成互相等待而锁死.主队列同步任务等待主线程执行,主线程之后的任务等待主队列任务完成。

解决办法:在主队列外面套一层并发队列的异步任务.或者使用主队列异步任务

问题代码:

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent*)event

{

NSLog(@"START----START");

//情况1:主队列同步任务-----锁死

dispatch_sync(dispatch_get_main_queue(), ^{

NSLog(@"%@", [NSThreadcurrentThread]);

NSLog(@"锁死了吗?");

});

NSLog(@"deadBlock1--END");

NSLog(@"OVER------OVER");

}

运行结果:

造成线程锁死的几种情况_第1张图片

在当前队列的任务(无论同步异步)里面,添加当前队列同步任务,造成锁死当前线程,该同步任务之后的任务不会执行


原因:(官方文档)Do not call the dispatch_sync function from a

task that is executing on the same queue that you pass to your function

call. Doing so will deadlock the queue. If you need to dispatch to the

current queue, do so asynchronously using the dispatch_async function.

说明:以上说法不完全正确,虽然在并发队列/全局队列的任务里面,添加当前并发队列同步任务不会造成锁死,但是苹果官方不建议这样做.

解决办法:使用dispatch_async添加异步任务

问题代码:

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent*)event

{

NSLog(@"START----START");

//会锁死

dispatch_queue_tqueue=dispatch_queue_create("串行队列",NULL);

//

dispatch_queue_t queue=dispatch_get_main_queue();

//不会锁死,不建议使用

//dispatch_queue_t

queue=dispatch_queue_create("并发队列",

DISPATCH_QUEUE_CONCURRENT);

//dispatch_queue_t

queue=dispatch_get_global_queue(0, 0);

dispatch_async(queue, ^{

NSLog(@"%@", [NSThreadcurrentThread]);

//在这之后的任务不会执行,因为会该同步任务会造成死锁

dispatch_sync(queue, ^{

NSLog(@"锁死了吗?");

});

NSLog(@"没有--没有--没有");

});

NSLog(@"deadBlock2--END");

NSLog(@"OVER------OVER");

}

运行结果

多个NSOperation之间循环依赖


原因:任务之间相互等待,造成死锁

解决办法:添加依赖的时候特别注意,不要有循环依赖

问题代码

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent*)event

{

//创建队列

NSOperationQueue*queue=[NSOperationQueuenew];

NSBlockOperation*blockOp1=[NSBlockOperationblockOperationWithBlock:^{

[NSThreadsleepForTimeInterval:2];

NSLog(@"我是任务1--%@", [NSThreadcurrentThread]);

}];

NSBlockOperation*blockOp2=[NSBlockOperationblockOperationWithBlock:^{

[NSThreadsleepForTimeInterval:2];

NSLog(@"我是任务2--%@", [NSThreadcurrentThread]);

}];

NSBlockOperation*blockOp3=[NSBlockOperationblockOperationWithBlock:^{

[NSThreadsleepForTimeInterval:2];

NSLog(@"我是任务3--%@", [NSThreadcurrentThread]);

}];

NSBlockOperation*blockOp4=[NSBlockOperationblockOperationWithBlock:^{

NSLog(@"我是任务4--%@", [NSThreadcurrentThread]);

}];

//注意:千万不要有循环依赖:即循环等待

[blockOp2addDependency:blockOp1];

[blockOp3addDependency:blockOp2];

[blockOp4addDependency:blockOp3];

//循环依赖,导致相互等待,相互锁死,所有任务都不会执行

[blockOp1addDependency:blockOp4];

[queueaddOperations:@[blockOp1,blockOp2,blockOp3,blockOp4]waitUntilFinished:NO];

NSLog(@"到这里了吗");

}

运行结果

造成线程锁死的几种情况_第2张图片

总结


使用dispatch_sync时候必须要慎重或者少用.如果要顺序执行可以用串行队列异步任务代替

最好不要在当前队列的任务里面,添加当前队列同步任务,会造成当前线程锁死,导致之后的任务不会执行.特别是当前线程是主线程的时候后果很严重.

stackoverflow相关讨论:Posts containing 'dispatch_sync in dispatch_async' - Stack Overflow

福利


造成线程锁死的几种情况_第3张图片

你可能感兴趣的:(造成线程锁死的几种情况)