造成线程锁死的几种情况

作者: 章鱼哥你好 | 来源:发表于2016-06-01 14:24 被阅读849次

主队列添加剂同步任务


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

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

问题代码:

-(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");

}

运行结果:

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


原因:(官方文档)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(@"到这里了吗");

}

运行结果

总结


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

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

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

福利

相关文章

  • 造成线程锁死的几种情况

    主队列添加剂同步任务 原因:对于主队列无论是同步异步都不会创建线程,而且主队列中的任务只有在主线程空闲的时候才会执...

  • Go 的并发模式(中)(更新中)

    有几种情况都会发生堵塞,一旦发生堵塞就会造成锁死 第一种情况只有发送没有接受,就会造成 blocking 第二种情...

  • 如何避免死锁

    死琐 A线程持有a锁,等待获取b锁;同时B线程持有b锁,等待获取a锁。 死琐条件 -- 独占锁: 互斥:资源不能被...

  • 线程锁

    iOS中有几种线程锁:@synchronized、NSLock以及NSRecursiveLock(递归锁)。本文用...

  • Redis应用-分布式锁

    锁是多线程编程的一个重要功能,它主要用于防止多个线程同时访问一个资源,从而造成资源出问题的情况。 传统的锁是在单机...

  • NSRecursiveLock递归锁

    递归锁,它允许同一线程多次加锁,而不会造成死锁。以下的代码如果用NSLock就会造成死锁: //普通线程锁NSLo...

  • iOS中的八大锁解析与使用

    线程安全:多线程操作共享数据,不会造成意想不到的问题锁的意义:为了线程安全 锁的分类 自旋锁 busy-waiti...

  • CAS

    1什么是CAS     CAS(Compare And Swap),即比较并交换,是解决多线程并行情况下使用锁造成...

  • 多线程-CAS

    一、什么是CAS? CAS,全称Compare And Swap(比较与交换),解决多线程并行情况下使用锁造成性能...

  • 2020-03-11 公平锁与非公平锁

    补: 公平锁:多个线程情况下排队,先到先获得锁 非公平锁:当锁被释放后,所有线程竞争锁,抢到的线程就会获得锁 非公...

网友评论

    本文标题:造成线程锁死的几种情况

    本文链接:https://www.haomeiwen.com/subject/azehdttx.html