Ios 从自定义串行队列同步主队列上的调度任务
我遇到了一个与iOS中的队列死锁相关的非常有趣的问题。有没有办法避免这种情况 考虑这一点:Ios 从自定义串行队列同步主队列上的调度任务,ios,multithreading,concurrency,grand-central-dispatch,Ios,Multithreading,Concurrency,Grand Central Dispatch,我遇到了一个与iOS中的队列死锁相关的非常有趣的问题。有没有办法避免这种情况 考虑这一点: 创建自定义串行队列 在此串行队列上异步分派一些任务(#1) 上的异步任务(#1)将一些任务(#2)分派到主队列同步 主队列将一些任务(#3)分派到串行队列同步上 结果-死锁 下面是这方面的示例代码 由于self.opQueue是一个串行队列,任务1完成后,任务3才会启动 由于任务#1正在调用主队列同步,因此在主队列完成任务#2之前,它永远不会完成 由于主队列正在等待opQueue完成任务#3,而opQu
- 由于self.opQueue是一个串行队列,任务1完成后,任务3才会启动
- 由于任务#1正在调用主队列同步,因此在主队列完成任务#2之前,它永远不会完成
- 由于主队列正在等待opQueue完成任务#3,而opQueue正在等待主队列完成任务#2,因此存在死锁
#import "ViewController.h" @interface ViewController () @property(nonatomic,strong) dispatch_queue_t opQueue; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; dispatch_queue_t queue = dispatch_queue_create("com.tarun.sqqueue", DISPATCH_QUEUE_SERIAL); self.opQueue = queue; [self performOperations]; } /// 1. Dispatch on serial queue async. /// 2. This async task on serial queue dispatchs some task onto /// main queue sync. /// 3. Main queue dispatched some task onto serial queue sync. /// 4. Result - DeadLock - (void)performOperations { /// task#1: Dispatch task on the serial Queue Asynchronously. /// So this is not blocking. dispatch_async(self.opQueue, ^{ for (int i = 1; i<=100; i++) { NSLog(@"%d. Async on Serial Queue from Main Queue.",i); } /// task#2: Dispatching task on main queue synchronously from serial /// queue.So this queue will wait till main queue executes this task.(Blocking) dispatch_sync(dispatch_get_main_queue(), ^{ for (int i = 1; i<=100; i++) { NSLog(@"%d. Sync on main queue from Serial Queue.",i); } }); }); /// task#3: Dispatching task on swrial queue synchronously from main /// queue.So main queue will wait till serial queue executes this task. (Blocking) dispatch_sync(self.opQueue, ^{ for (int i = 1; i<=100; i++) { NSLog(@"%d. Sync on Serial Queue From Main Queue.",i); } }); /// Since self.opQueue is a serial queue, task#3 will not start till task#1 completes. /// Since task#1 is calling main queue sync, /// so it will never complete till main queue completes task#2. /// Since main queue is waiting for opQueue to finish task#3, and opQueue is waiting for main queue to finish task#2 there is a deadlock. NSLog(@"Back to main queue"); } @end
#导入“ViewController.h” @界面视图控制器() @属性(非原子,强)调度队列; @结束 @实现视图控制器 -(无效)viewDidLoad{ [超级视图下载]; dispatch\u queue\u t queue=dispatch\u queue\u create(“com.tarun.sqqueue”, 调度队列(串行); self.opQueue=队列; [自我执行操作]; } /// 1. 串行队列异步调度。 /// 2. 这个串行队列上的异步任务将一些任务分派到 ///主队列同步。 /// 3. 主队列将一些任务分派到串行队列同步。 /// 4. 结果-死锁 -(无效)性能操作{ ///任务#1:异步在串行队列上调度任务。 ///所以这不是阻塞。 调度异步(self.opQueue^{ 对于苹果公司的(inti=1;i) 重要提示:您不应调用调度同步或调度同步 从与您在同一队列中执行的任务执行函数 计划传递到功能。这对于 串行队列,保证死锁,但也应 避免使用并发队列
这是一个有保证的死锁。避免这种情况的唯一方法是不要以这种方式实现它。是的,不要这样做。特别是在串行队列上同步调度同步任务,同步调度其他任务会带来麻烦,除非您知道在这里使用的是哪些队列,异步任务是同步调度的。但我不是dispat同步发送到同一队列。假设自定义串行队列是框架/库的一部分,并公开供应用程序使用。那么框架对其没有控制权,那么如何避免这种情况呢?但您正在发送到同一队列;不是直接发送,但这不重要。通常情况下,框架不会k将公开队列供其他人使用。框架可以在内部使用队列来管理关键部分,也可以接受调用者的队列,但框架提供队列是个坏主意。是的,这是一种假设情况,理想情况下,框架永远不会将队列公开给外部人使用,但理论上仍然如此很可能也很容易陷入僵局。所以我只是想知道有什么办法可以避免这种情况。