美文网首页
GCD-线程栅栏

GCD-线程栅栏

作者: 153037c65b0c | 来源:发表于2020-02-28 17:24 被阅读0次

    GCD的线程栅栏分为同步栅栏(dispatch_barrier_sync)和异步栅栏(dispatch_barrier_async)
    同步栅栏:
    -同步栅栏中的任务会等之前添加到同一队列的任务都结束后开始按顺序执行。
    -同步栅栏的任务会在主线程运行,会阻塞当前代码,等栅栏函数中的任务完成后才会接着执行之后的代码,相当于开启了一个同步任务。
    异步栅栏:
    -异步栅栏中的任务会等之前添加到同一队列的任务都结束后开始按顺序执行。
    -异步栅栏中的任务不在主线程运行,不会阻塞异步栅栏之后主线程的代码。

    1.同步栅栏

        dispatch_queue_t queue = dispatch_queue_create("barrierQueue", DISPATCH_QUEUE_CONCURRENT);
        for (int i = 0; i < 3; i++) {
            dispatch_async(queue, ^{
                sleep(1);
                NSLog(@"栅栏前任务%d 线程%@", i, [NSThread currentThread]);
            });
        }
        NSLog(@"代码经过栅栏前");
        dispatch_barrier_sync(queue, ^{
            NSLog(@"栅栏任务1,线程%@", [NSThread currentThread]);
            sleep(1);
        });
        dispatch_barrier_sync(queue, ^{
            NSLog(@"栅栏任务2,线程%@", [NSThread currentThread]);
            sleep(1);
        });
        NSLog(@"代码通过栅栏");
        for (int i = 0; i < 3; i++) {
            dispatch_async(queue, ^{
                sleep(1);
                NSLog(@"栅栏后任务%d 线程%@", i, [NSThread currentThread]);
            });
        }
    

    运行结果:

    2020-02-28 17:07:42.011765+0800 Test[24412:1701334] 代码经过栅栏前
    2020-02-28 17:07:42.011890+0800 Test[24412:1701446] 栅栏前任务开始2 线程<NSThread: 0x600000364c80>{number = 5, name = (null)}
    2020-02-28 17:07:42.011891+0800 Test[24412:1701439] 栅栏前任务开始0 线程<NSThread: 0x600000364bc0>{number = 3, name = (null)}
    2020-02-28 17:07:42.011919+0800 Test[24412:1701445] 栅栏前任务开始1 线程<NSThread: 0x600000364a80>{number = 4, name = (null)}
    2020-02-28 17:07:43.014260+0800 Test[24412:1701446] 栅栏前任务结束2 线程<NSThread: 0x600000364c80>{number = 5, name = (null)}
    2020-02-28 17:07:43.014260+0800 Test[24412:1701439] 栅栏前任务结束0 线程<NSThread: 0x600000364bc0>{number = 3, name = (null)}
    2020-02-28 17:07:43.014301+0800 Test[24412:1701445] 栅栏前任务结束1 线程<NSThread: 0x600000364a80>{number = 4, name = (null)}
    2020-02-28 17:07:43.014488+0800 Test[24412:1701334] 栅栏任务1,线程<NSThread: 0x6000003eafc0>{number = 1, name = main}
    2020-02-28 17:07:44.014744+0800 Test[24412:1701334] 栅栏任务2,线程<NSThread: 0x6000003eafc0>{number = 1, name = main}
    2020-02-28 17:07:45.016132+0800 Test[24412:1701334] 代码通过栅栏
    2020-02-28 17:07:46.019509+0800 Test[24412:1701445] 栅栏后任务0 线程<NSThread: 0x600000364a80>{number = 4, name = (null)}
    2020-02-28 17:07:46.019552+0800 Test[24412:1701446] 栅栏后任务1 线程<NSThread: 0x600000364c80>{number = 5, name = (null)}
    2020-02-28 17:07:46.019567+0800 Test[24412:1701444] 栅栏后任务2 线程<NSThread: 0x600000365400>{number = 6, name = (null)}
    

    观察结果可以看到,主线程的"代码通过栅栏"在栅栏任务结束后才打印,并且栅栏任务所在的线程是主线程,所以同步栅栏会阻塞主线程,同步之后的代码要等到同步栅栏的任务完成后才会去执行。
    观察栅栏任务0,1,2和同步栅栏任务1,2可以得出,同步栅栏中的任务要等栅栏前添加到同一队列的任务完成,才会按顺序执行。

    2.异步栅栏

        dispatch_queue_t queue = dispatch_queue_create("barrierAsyncQueue", DISPATCH_QUEUE_CONCURRENT);
        for (int i = 0; i < 3; i++) {
            dispatch_async(queue, ^{
                NSLog(@"栅栏前任务开始%d 线程%@", i, [NSThread currentThread]);
                sleep(1);
                NSLog(@"栅栏前任务结束%d 线程%@", i, [NSThread currentThread]);
            });
        }
        NSLog(@"代码经过栅栏前");
        dispatch_barrier_async(queue, ^{
            NSLog(@"栅栏任务1,线程%@", [NSThread currentThread]);
            sleep(1);
        });
        dispatch_barrier_async(queue, ^{
            NSLog(@"栅栏任务2,线程%@", [NSThread currentThread]);
            sleep(1);
        });
        NSLog(@"代码通过栅栏");
        for (int i = 0; i < 3; i++) {
            dispatch_async(queue, ^{
                NSLog(@"栅栏后任务开始%d 线程%@", i, [NSThread currentThread]);
                sleep(1);
                NSLog(@"栅栏后任务结束%d 线程%@", i, [NSThread currentThread]);
            });
        }
    

    运行结果:

    2020-02-28 17:22:31.951608+0800 Test[24630:1724365] 代码经过栅栏前
    2020-02-28 17:22:31.951707+0800 Test[24630:1724600] 栅栏前任务开始1 线程<NSThread: 0x600002cde540>{number = 4, name = (null)}
    2020-02-28 17:22:31.951745+0800 Test[24630:1724816] 栅栏前任务开始2 线程<NSThread: 0x600002cde600>{number = 5, name = (null)}
    2020-02-28 17:22:31.951779+0800 Test[24630:1724590] 栅栏前任务开始0 线程<NSThread: 0x600002c3aa40>{number = 3, name = (null)}
    2020-02-28 17:22:31.951923+0800 Test[24630:1724365] 代码通过栅栏
    2020-02-28 17:22:32.953949+0800 Test[24630:1724600] 栅栏前任务结束1 线程<NSThread: 0x600002cde540>{number = 4, name = (null)}
    2020-02-28 17:22:32.953997+0800 Test[24630:1724816] 栅栏前任务结束2 线程<NSThread: 0x600002cde600>{number = 5, name = (null)}
    2020-02-28 17:22:32.954026+0800 Test[24630:1724590] 栅栏前任务结束0 线程<NSThread: 0x600002c3aa40>{number = 3, name = (null)}
    2020-02-28 17:22:32.954666+0800 Test[24630:1724590] 栅栏任务1开始,线程<NSThread: 0x600002c3aa40>{number = 3, name = (null)}
    2020-02-28 17:22:33.955252+0800 Test[24630:1724590] 栅栏任务1结束,线程<NSThread: 0x600002c3aa40>{number = 3, name = (null)}
    2020-02-28 17:22:33.955545+0800 Test[24630:1724590] 栅栏任务2开始,线程<NSThread: 0x600002c3aa40>{number = 3, name = (null)}
    2020-02-28 17:22:34.956239+0800 Test[24630:1724590] 栅栏任务2结束,线程<NSThread: 0x600002c3aa40>{number = 3, name = (null)}
    2020-02-28 17:22:35.960067+0800 Test[24630:1724816] 栅栏后任务1 线程<NSThread: 0x600002cde600>{number = 5, name = (null)}
    2020-02-28 17:22:35.960067+0800 Test[24630:1724600] 栅栏后任务2 线程<NSThread: 0x600002cde540>{number = 4, name = (null)}
    2020-02-28 17:22:35.960067+0800 Test[24630:1724590] 栅栏后任务0 线程<NSThread: 0x600002c3aa40>{number = 3, name = (null)}
    
    

    观察结果可以看到,主线程的"代码通过栅栏"在栅栏任务开始前就打印,并且异步栅栏任务在子线程执行,所以异步栅栏任务不会阻塞栅栏后面主线程的代码。
    观察栅栏任务0,1,2和异步栅栏任务1,2可以得出,异步栅栏中的任务要等栅栏前添加到同一队列的任务完成,才会按顺序执行。

    相关文章

      网友评论

          本文标题:GCD-线程栅栏

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