GCD(一)-dispatch_barrier_async

6433 ワード

前に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(" ")

印刷結果:
 
11
{number = 2, name = (null)}
12
{number = 2, name = (null)}
13
{number = 2, name = (null)}
14
{number = 2, name = (null)}
5
{number = 2, name = (null)}
6
{number = 2, name = (null)}
説明は非同期で実行され、次に最初の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(" ")

実行結果:
 
14
14
14
5
6
{number = 3, name = (null)}
{number = 2, name = (null)}
{number = 4, name = (null)}
{number = 5, name = (null)}
{number = 6, name = (null)}
11
{number = 7, name = (null)}
各dispatch_が明らかに表示されます.barrier_async(currentQueue){}フェンス関数は、いずれも非同期関数である.実行する印刷も交差する.読み出したnum値も、私たちが望んでいるものではありません.データが暴走する現象が現れる.
シリアル化キューに送信されるコードは次のとおりです.
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(" ")

出力結果:
 
11
{number = 2, name = (null)}
12
{number = 2, name = (null)}
13
{number = 2, name = (null)}
14
{number = 2, name = (null)}
5
{number = 2, name = (null)}
6
{number = 2, name = (null)}
説明:確かに順次実行する、シリアル化キューであることがわかる.コードブロックをコミットするキューはシリアル化されたキューであるからです.上記のように実行結果は、次のコードの効果と同じです.
 dispatch_barrier_async(currentQueue) {
        print("6")
        print(NSThread.currentThread())
    }

コミットされたキューがシリアルキューである場合、下のキューは上のキューに置き換えることができます.
dispatch_async(currentQueue) {
        print("6")
        print(NSThread.currentThread())
    }