美文网首页
GCD之信号量(并发做成串行)

GCD之信号量(并发做成串行)

作者: 路有点颠簸 | 来源:发表于2020-06-17 14:14 被阅读0次

GCD三个函数的操作:
dispatch_semaphore_create 创建一个semaphore
dispatch_semaphore_signal 发送一个信号
dispatch_semaphore_wait 等待信号
简单的介绍一下这三个函数,第一个函数有一个整形的参数,我们可以理解为信号的总量,dispatch_semaphore_signal是发送一个信号,自然会让信号总量加1,dispatch_semaphore_wait等待信号,当信号总量少于0的时候就会一直等待,否则就可以正常的执行,并让信号总量-1,根据这样的原理,我们便可以快速的创建一个并发控制来同步任务和有限资源访问控制。

下面是一道我参加的机试题,虽然结局难免令人遗憾,第一次机试太紧张,提交的答案做错了,后来又想了一下,做个记录吧

- (void)bbb{
    __block dispatch_semaphore_t sema = dispatch_semaphore_create(0);
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        for (int i = 0; i<5; i++) {
            if (i != 0) {
                dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
            }
            NSLog(@"******Began:%d********",i);
            NSLog(@"线程A输出======%d,%@",i,[NSThread currentThread]);
            dispatch_semaphore_signal(sema);
        }
    });
    
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        for (int i = 0; i<5; i++) {
            dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
            NSLog(@"线程B输出======%d,%@",i,[NSThread currentThread]);
            dispatch_semaphore_signal(sema);
        }
    });
    
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        for (int i = 0; i<5; i++) {
            dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
            NSLog(@"线程C输出======%d,%@",i,[NSThread currentThread]);
            NSLog(@"******end:%d********",i);
            dispatch_semaphore_signal(sema);
        }
    });
}

控制台输出

2020-06-17 17:24:40.442372+0800 demo[65114:2856626] ******Began:0********
2020-06-17 17:24:40.442564+0800 demo[65114:2856626] 线程A输出======0,<NSThread: 0x600002cb4080>{number = 3, name = (null)}
2020-06-17 17:24:40.442765+0800 demo[65114:2856623] 线程B输出======0,<NSThread: 0x600002ce1840>{number = 4, name = (null)}
2020-06-17 17:24:40.442939+0800 demo[65114:2856622] 线程C输出======0,<NSThread: 0x600002cb0100>{number = 5, name = (null)}
2020-06-17 17:24:40.443110+0800 demo[65114:2856622] ******end:0********
2020-06-17 17:24:40.443256+0800 demo[65114:2856626] ******Began:1********
2020-06-17 17:24:40.443392+0800 demo[65114:2856626] 线程A输出======1,<NSThread: 0x600002cb4080>{number = 3, name = (null)}
2020-06-17 17:24:40.443531+0800 demo[65114:2856623] 线程B输出======1,<NSThread: 0x600002ce1840>{number = 4, name = (null)}
2020-06-17 17:24:40.443660+0800 demo[65114:2856622] 线程C输出======1,<NSThread: 0x600002cb0100>{number = 5, name = (null)}
2020-06-17 17:24:40.443776+0800 demo[65114:2856622] ******end:1********
2020-06-17 17:24:40.443863+0800 demo[65114:2856626] ******Began:2********
2020-06-17 17:24:40.444072+0800 demo[65114:2856626] 线程A输出======2,<NSThread: 0x600002cb4080>{number = 3, name = (null)}
2020-06-17 17:24:40.444324+0800 demo[65114:2856623] 线程B输出======2,<NSThread: 0x600002ce1840>{number = 4, name = (null)}
2020-06-17 17:24:40.449068+0800 demo[65114:2856622] 线程C输出======2,<NSThread: 0x600002cb0100>{number = 5, name = (null)}
2020-06-17 17:24:40.449171+0800 demo[65114:2856622] ******end:2********
2020-06-17 17:24:40.449275+0800 demo[65114:2856626] ******Began:3********
2020-06-17 17:24:40.449415+0800 demo[65114:2856626] 线程A输出======3,<NSThread: 0x600002cb4080>{number = 3, name = (null)}
2020-06-17 17:24:40.449570+0800 demo[65114:2856623] 线程B输出======3,<NSThread: 0x600002ce1840>{number = 4, name = (null)}
2020-06-17 17:24:40.449697+0800 demo[65114:2856622] 线程C输出======3,<NSThread: 0x600002cb0100>{number = 5, name = (null)}
2020-06-17 17:24:40.449792+0800 demo[65114:2856622] ******end:3********
2020-06-17 17:24:40.449886+0800 demo[65114:2856626] ******Began:4********
2020-06-17 17:24:40.449996+0800 demo[65114:2856626] 线程A输出======4,<NSThread: 0x600002cb4080>{number = 3, name = (null)}
2020-06-17 17:24:40.450127+0800 demo[65114:2856623] 线程B输出======4,<NSThread: 0x600002ce1840>{number = 4, name = (null)}
2020-06-17 17:24:40.450284+0800 demo[65114:2856622] 线程C输出======4,<NSThread: 0x600002cb0100>{number = 5, name = (null)}
2020-06-17 17:24:40.450528+0800 demo[65114:2856622] ******end:4********

解释一下,三个异步操作分别执行for循环,在线程B和C的for循环开始都做了wait操作,所以必然是线程A先执行
Q:线程C执行完一次end后发出信号量,明明线程A和B都在wait,为什么线程A先执行i=1?
A:线程A执行完i=0后就在wait状态,所以第二轮依然是线程A先执行。

相关文章

  • GCD之信号量(并发做成串行)

    GCD三个函数的操作:dispatch_semaphore_create 创建一个semaphoredispatc...

  • iOS开发多线程之GCD

    iOS开发多线程之GCDiOS开发之GCD同步任务加强iOS开发之GCD串行队列iOS开发之GCD并发队列 GCD...

  • iOS开发之GCD并发队列

    iOS开发多线程之GCDiOS开发之GCD同步任务加强iOS开发之GCD串行队列iOS开发之GCD并发队列 03 ...

  • iOS开发之GCD同步任务加强

    iOS开发多线程之GCDiOS开发之GCD同步任务加强iOS开发之GCD串行队列iOS开发之GCD并发队列 004...

  • iOS开发之GCD串行队列

    iOS开发多线程之GCDiOS开发之GCD同步任务加强iOS开发之GCD串行队列iOS开发之GCD并发队列 实例d...

  • GCD 死锁

    GCD死锁 同步 异步 串行 并发

  • GCD队列使用

    使用GCD前,先对队列总结一下: 串行和并发 GCD中队列分为两种:串行队列、并发队列。串行队列:任务按在队列里的...

  • iOS面试8 - 多线程

    GCD 同步异步, 串行并发同步串行: dispatch_sync(serial_queue, ^{ // wor...

  • iOS 顺序执行

    打印结果 GCD 信号量控制并发 (dispatch_semaphore)

  • iOS面试 -- 多线程相关

    多线程技术方案 GCD NSOperation NSThread GCD 同步/异步 和串行/并发 dispatc...

网友评论

      本文标题:GCD之信号量(并发做成串行)

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