• iOS Dispatch_sync 阻塞线程的原因


    大家的知道在主队列上使用dispatch_sync(),

    - (void)testSyncMainThread {
        
        dispatch_queue_t main = dispatch_get_main_queue();
        NSLog(@"*********1");
        dispatch_sync(main, ^(){
                NSLog(@"*********2");
        });
        NSLog(@"*********3");
    }

    会造成线程阻塞,但是查找网上说的原因,发现基本上说法都是一样的,感觉不是不太好理解,

    我查看一下API, 

    /*!

     * @function dispatch_sync

     *

     * @abstract

     * Submits a block for synchronous execution on a dispatch queue.

     *

     * @discussion

     * Submits a workitem to a dispatch queue like dispatch_async(), however

     * dispatch_sync() will not return until the workitem has finished.

     *

     * Work items submitted to a queue with dispatch_sync() do not observe certain

     * queue attributes of that queue when invoked (such as autorelease frequency

     * and QOS class).

     *

     * Calls to dispatch_sync() targeting the current queue will result

     * in dead-lock. Use of dispatch_sync() is also subject to the same

     * multi-party dead-lock problems that may result from the use of a mutex.

     * Use of dispatch_async() is preferred.

     *

     * Unlike dispatch_async(), no retain is performed on the target queue. Because

     * calls to this function are synchronous, the dispatch_sync() "borrows" the

     * reference of the caller.

     *

     * As an optimization, dispatch_sync() invokes the workitem on the thread which

     * submitted the workitem, except when the passed queue is the main queue or

     * a queue targetting it (See dispatch_queue_main_t,

     * dispatch_set_target_queue()).

     *

     * @param queue

     * The target dispatch queue to which the block is submitted.

     * The result of passing NULL in this parameter is undefined.

     *

     * @param block

     * The block to be invoked on the target dispatch queue.

     * The result of passing NULL in this parameter is undefined.

     */

    结合API,我的理解:

    第一步:当代码执行到 dispatch_sync()时,会首先把dispatch_sync()函数放到当前线程的队列(就是主队列中),而且这个线程并不会立即返回,而是会等待block中的任务都完成时才会返回,

    第二步:再把block中的任务依次放到主队列中等待执行,

    由于是同步执行,而且block中的任务在主队列的线性表中的前面有个dispatch_sync()等待完成,而dispatch_sync()的完成又依赖于block的执行完成,就这样造成了死锁。

    最后:在其他队列上模拟这种死锁情况

     dispatch_queue_t lwMainQueue = dispatch_queue_create("lw.queue", DISPATCH_QUEUE_SERIAL);
        dispatch_sync(lwMainQueue, ^{
            NSLog(@"*********1");
            dispatch_sync(lwMainQueue, ^{NSLog(@"*********2");
            });
        NSLog(@"*********3");
        });

    效果是一样的

  • 相关阅读:
    java 基础(Collections 工具类的常用方法)
    Java 基础( Map 实现类: Properties)
    Java 基础(Map)
    Java 基础(集合三)
    Java 基础(集合二)
    Java 基础(集合一)
    Java 基础(Annotation)
    CentOS7 系统 springboot应用启动脚本
    GenericObjectPool源码分析
    问题springboot项目启动报错
  • 原文地址:https://www.cnblogs.com/liuwenqiang/p/10943840.html
Copyright © 2020-2023  润新知