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

我遇到了一个与iOS中的队列死锁相关的非常有趣的问题。有没有办法避免这种情况

考虑这一点:

  • 创建自定义串行队列
  • 在此串行队列上异步分派一些任务(#1)
  • 上的异步任务(#1)将一些任务(#2)分派到主队列同步
  • 主队列将一些任务(#3)分派到串行队列同步上
  • 结果-死锁
  • 下面是这方面的示例代码

    • 由于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将公开队列供其他人使用。框架可以在内部使用队列来管理关键部分,也可以接受调用者的队列,但框架提供队列是个坏主意。是的,这是一种假设情况,理想情况下,框架永远不会将队列公开给外部人使用,但理论上仍然如此很可能也很容易陷入僵局。所以我只是想知道有什么办法可以避免这种情况。