美文网首页
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之信号量(并发做成串行)

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