GCD(一) - dispatch_barrier_async

作者: 司马捷 | 来源:发表于2016-05-25 17:08 被阅读305次

    之前总结过很多GCD的用法,好久没用了,这次再总结一下.做个笔记.个人理解,欢迎交流....

    void dispatch_barrier_async( dispatch_queue_t queue, dispatch_block_t block);
    

    文档解释:Submits a barrier block for asynchronous execution and returns immediately.
    就是这个函数提交一个比较耗时的代码块 到一个异步操作上,并立即返回.我理解这就是异步操作.

    Discussion 详细说明
    Calls to this function always return immediately after the block has been submitted and never wait for the block to be invoked.
    我理解就是 提交代码块以后,不做任何等待,直接返回.也就是异步.
    When the barrier block reaches the front of a private concurrent queue, it is not executed immediately.
    当这个代码块被提交到 一个私有的并发队列上的时候,代码块不会被理解执行.
    Instead, the queue waits until its currently executing blocks finish executing.
    相应的是等到这个队列当前正在执行的代码块执行完毕以后,才会执行.
    At that point, the barrier block executes by itself. Any blocks submitted after the barrier block are not executed until the barrier block completes.
    同样的,在这个阻塞的代码块之后 提交到这个队列上的代码块 都不会被执行,直到这个阻塞的代码块执行完.

    但是这里有个问题:
    The queue you specify should be a concurrent queue that you create yourself using the dispatch_queue_create function. If the queue you pass to this function is a serial queue or one of the global concurrent queues, this function behaves like the dispatch_async function.
    调用这个方法,传递的queue 队列,需要指定一个并发队列,并且是 用 dispatch_queue_create 这个函数创建的.
    否则,如果传递的队列是一个串行的队列,或者是一个全局的并发队列.那么这个函数的使用效果,就是和一个简单的异步dispatch_async函数效果一样了.

    看下面代码传递 一个私有的并发队列:

     let currentQueue:dispatch_queue_t = dispatch_queue_create("com.eric", DISPATCH_QUEUE_CONCURRENT);
        
        var num = 10
        dispatch_barrier_async(currentQueue) {
            sleep(1)
            num = 11
            print(num)
            print(NSThread.currentThread())
        }
        dispatch_barrier_async(currentQueue) {
            num = 12
            print(num)
            print(NSThread.currentThread())
        }
        dispatch_barrier_async(currentQueue) {
            num = 13
            print(num)
            print(NSThread.currentThread())
        }
        dispatch_barrier_async(currentQueue) {
            num = 14
            print(num)
            print(NSThread.currentThread())
        }
        dispatch_barrier_async(currentQueue) {
            print("5")
            print(NSThread.currentThread())
        }
        dispatch_barrier_async(currentQueue) {
            print("6")
            print(NSThread.currentThread())
        }
        print("结束")
    

    打印结果:
    <pre>结束
    11
    <NSThread: 0x12cd1ee80>{number = 2, name = (null)}
    12
    <NSThread: 0x12cd1ee80>{number = 2, name = (null)}
    13
    <NSThread: 0x12cd1ee80>{number = 2, name = (null)}
    14
    <NSThread: 0x12cd1ee80>{number = 2, name = (null)}
    5
    <NSThread: 0x12cd1ee80>{number = 2, name = (null)}
    6
    <NSThread: 0x12cd1ee80>{number = 2, name = (null)}</pre>

    说明是异步执行,其次在第一个 dispatch_barrier_async(currentQueue) { }中添加sleep()阻塞了线程,后面的 dispatch_barrier_async(currentQueue) {}方法全部被阻塞住了.因为我们传递的参数是我们自己创建的一个私有队列.

    但是如果我们传递的queue是其它的,上面提到的全局并发队列或者串行化队列看下代码:
    let currentQueue:dispatch_queue_t = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
        var num = 10
        dispatch_barrier_async(currentQueue) {
            sleep(1)
            num = 11
            print(num)
            print(NSThread.currentThread())
        }
        dispatch_barrier_async(currentQueue) {
            num = 12
            print(num)
            print(NSThread.currentThread())
        }
        dispatch_barrier_async(currentQueue) {
            num = 13
            print(num)
            print(NSThread.currentThread())
        }
        dispatch_barrier_async(currentQueue) {
            num = 14
            print(num)
            print(NSThread.currentThread())
        }
        dispatch_barrier_async(currentQueue) {
            print("5")
            print(NSThread.currentThread())
        }
        dispatch_barrier_async(currentQueue) {
            print("6")
            print(NSThread.currentThread())
        }
        print("结束")
    

    执行结果:
    <pre>结束
    14
    14
    14
    5
    6
    <NSThread: 0x12de57f80>{number = 3, name = (null)}
    <NSThread: 0x12de16800>{number = 2, name = (null)}
    <NSThread: 0x12de5b4b0>{number = 4, name = (null)}
    <NSThread: 0x12de5dde0>{number = 5, name = (null)}
    <NSThread: 0x12de512c0>{number = 6, name = (null)}
    11
    <NSThread: 0x12de2bfd0>{number = 7, name = (null)}
    </pre>
    很明显可以看到每个 dispatch_barrier_async(currentQueue) {}栅栏函数,都是一个异步函数.执行的打印也交叉出现.读取的num值,也并不是我们想要的.出现数据乱窜的现象.</pre>

    下面是提交到串行化队列的代码:
    let currentQueue:dispatch_queue_t = dispatch_queue_create("com.eric", DISPATCH_QUEUE_SERIAL);
        //let currentQueue:dispatch_queue_t = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
        var num = 10
        dispatch_barrier_async(currentQueue) {
            sleep(5)
            num = 11
            print(num)
            print(NSThread.currentThread())
        }
        dispatch_barrier_async(currentQueue) {
            num = 12
            print(num)
            print(NSThread.currentThread())
        }
        dispatch_barrier_async(currentQueue) {
            num = 13
            print(num)
            print(NSThread.currentThread())
        }
        dispatch_barrier_async(currentQueue) {
            num = 14
            print(num)
            print(NSThread.currentThread())
        }
        dispatch_barrier_async(currentQueue) {
            print("5")
            print(NSThread.currentThread())
        }
        dispatch_barrier_async(currentQueue) {
            print("6")
            print(NSThread.currentThread())
        }
        print("结束")
    

    输出结果:
    <pre>结束
    11
    <NSThread: 0x15f524d40>{number = 2, name = (null)}
    12
    <NSThread: 0x15f524d40>{number = 2, name = (null)}
    13
    <NSThread: 0x15f524d40>{number = 2, name = (null)}
    14
    <NSThread: 0x15f524d40>{number = 2, name = (null)}
    5
    <NSThread: 0x15f524d40>{number = 2, name = (null)}
    6
    <NSThread: 0x15f524d40>{number = 2, name = (null)}</pre>

    说明:可以看出确实是顺序执行的,是串行化队列.因为我们提交代码块的队列是一个串行化的队列.按照上文提到执行结果和下面代码效果一样

     dispatch_barrier_async(currentQueue) {
            print("6")
            print(NSThread.currentThread())
        }
    

    当提交的队列是串行队列的时候, 下面的可以替换上面的

    dispatch_async(currentQueue) {
            print("6")
            print(NSThread.currentThread())
        }
    

    相关文章

      网友评论

        本文标题:GCD(一) - dispatch_barrier_async

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