19, iOS bottom Analysis - GCD (ii) Application of

GCD Application Analysis


1、dispatch_group_t  组 

GCD Thread Synchronization

For example: multiple simultaneous network requests (Example: Task 1, Task 2), which each want to do several tasks, etc. However, the task is completed and then performs the next task, in this scenario, the most common is the GCD group
 1, dispatch_group_async
 by dispatch_group_async () added to a team task 1, task 2, task 1 is performed and then by dispatch_group_notify (), task 2 will take over after the end of the task.

dispatch_queue_t globalQueue = dispatch_get_global_queue(0, 0);
    dispatch_group_t group = dispatch_group_create();
    dispatch_group_async(group, globalQueue, ^{
        sleep(1);
        NSLog(@"task 1");
    });
    
    dispatch_group_async(group, globalQueue, ^{
        sleep(1);
        NSLog(@"task 2");
    });
//全部执行完毕
    dispatch_group_notify(group, globalQueue, ^{
        NSLog(@"task done");
    });


 2, into the group and the group
    into the group: dispatch_group_enter (), (input) tells the group to add tasks to the queue of
    the group: dispatch_group_leave (), (leave) tells group a task execution is over, it is removed Group
    wait: dispatch_group_wait (), (waiting) blocks the current thread, when an equal number of leave and enter the number of times or more than the time will continue down the implementation.
    Complete: dispatch_group_notify (), equal number of times and enter the (notification) leave, and will run the task.
 Thus dispatch_group_leave () and dispatch_group_wait () to be used in pairs,
 in the above example, if the demand required to perform the task after task 12, may be modified as follows:

dispatch_queue_t globalQueue = dispatch_get_global_queue(0, 0);
    dispatch_group_t group = dispatch_group_create();
    
    dispatch_group_enter(group);
//    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), globalQueue, ^{
////        sleep(1);
//        NSLog(@"task 1");
//        dispatch_group_leave(group);
//    });
    dispatch_async(globalQueue, ^{
        sleep(2);
        NSLog(@"task 1");
        dispatch_group_leave(group);
    });
//永远等待,也就是当任务1不出组(移出),当前线程就永远等待。
    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);

    dispatch_group_enter(group);
    dispatch_async(globalQueue, ^{
        NSLog(@"task 2");
        dispatch_group_leave(group);
    });
//    NSLog(@"task 2");
//    dispatch_group_leave(group);
    
    //全部执行完毕。非线程阻塞
    dispatch_group_notify(group, globalQueue, ^{
        NSLog(@"task done");
    });
    NSLog(@"是否阻塞?");

dispatch_group_notify function does not block a thread, dispatch_group_wait blocks the thread.
dispatch_group_notify function can be added directly to the task, dispatch_group_wait function simply blocking the thread continues downward, it needs its own separate add "summary task"
 parameter queue dispatch_group_notify function of whether or not the dispatch_group_async queue is the same queue, will last execution


2、dispatch_barrier_async 

Obstruction blocking synchronous and asynchronous

2, dispatch_barrier_async hinder
 the Department of class Queue API is only valid for () created out by dispatch_queue_create DISPATCH_QUEUE_CONCURRENT (concurrent), if other queues, such as global or not () created by dispatch_queue_create concurrent queue, then dispatch_barrier_async / dispatch_barrier_sync will become to dispatch_async / dispatch_sync, lost particularity, that dispatch_barrier_async no effect "fence" of the.

    dispatch_queue_t queue = dispatch_queue_create("com.liujilou.barrier", DISPATCH_QUEUE_CONCURRENT);
    __block int a = 10;
    dispatch_async(queue, ^{
        NSLog(@"读取1  a=%d",a);
    });
    dispatch_async(queue, ^{
        NSLog(@"读取2  a=%d",a);
    });
    dispatch_async(queue, ^{
        NSLog(@"读取3  a=%d",a);
    });
//
    dispatch_barrier_async(queue, ^{
        sleep(1);
        NSLog(@"赋值 a=%d",a);
        a = 20;
    });
    NSLog(@"主线程执行");
    dispatch_async(queue, ^{
        NSLog(@"读取4  a=%d",a);
    });
    dispatch_async(queue, ^{
        NSLog(@"读取5  a=%d",a);
    });
/*
 2020-03-15 15:16:21.510753+0800 filedome[73509:2023353] 主线程执行
 2020-03-15 15:16:21.510763+0800 filedome[73509:2023414] 读取1  a=10
 2020-03-15 15:16:21.510781+0800 filedome[73509:2023415] 读取2  a=10
 2020-03-15 15:16:21.510783+0800 filedome[73509:2023416] 读取3  a=10
 2020-03-15 15:16:22.515361+0800 filedome[73509:2023416] 赋值 a=10
 2020-03-15 15:16:22.515739+0800 filedome[73509:2023415] 读取5  a=20
 2020-03-15 15:16:22.515736+0800 filedome[73509:2023416] 读取4  a=20
 */

By analysis shows the print result, is added prior to dispatch_barrier_async concurrent execution task queue (read 1-3), and the task will be performed in the dispatch_barrier_async after completion of execution of these tasks. Meanwhile dispatch_barrier_async will block the current thread, we need to complete the task in which the straight line z to continue behind these, but will not block the main thread, the main thread can execute properly. Executing the task continues behind the concurrent execution.
 Figure dispatch_barrier_async.png
 dispatch_barrier_sync will block the main thread.


3、dispatch_suspend() 和 dispatch_resume()

Suspend, resume queue

dispatch_suspend (queue) specified pending queue (with no need to perform operations of local excessive, suspend the queue, and then restore the queue);
 dispatch_resume (Queue) resume execution queue
 does not affect the processing has been performed. After suspended, added to the queue, the task has not been implemented will be suspended until recovery. After the recovery process continues.
 dispatch_suspend does not suspend the running of the block immediately, but after the current block execution is complete, the subsequent suspension of the execution block.
 To be used in pairs, whether by error.

 

4, dispatch_semaphore_create semaphore

Signals the semaphore is> = 1 time, allows, whether those not permitted. A locking mechanism for multi-threaded.

//    1、创建信号量为1
    dispatch_semaphore_t semaphoer = dispatch_semaphore_create(1);
//    2、等待 加锁
//    第一个参数 信号量。信号量 >=1 的时候允许通过。并对其进行 减1操作。
//    等待 第二个参数等待时间,这里用一个未来的时间也就是一直等待。
    dispatch_semaphore_wait(semaphoer, DISPATCH_TIME_FOREVER);
//    3、解锁
//    计数加1,相当于解锁。在任务执行完可以再次访问的时候进行加1 解锁
    dispatch_semaphore_signal(sem);
//    这三个步骤必须都有,否者会崩溃。
    dispatch_semaphore_t sem = dispatch_semaphore_create(1);
    //    计数 减 1
    long result = dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
    if (result == 0) {
        NSLog(@"task  1");
        //        计数 加 1
        dispatch_semaphore_signal(sem);
    }else{
        //        计数不为0的情况进行处理
        NSLog(@"task  2");
    }
dispatch_queue_t queue = dispatch_queue_create(0, 0);
    dispatch_semaphore_t sem = dispatch_semaphore_create(1);
    dispatch_async(queue, ^{
        for (int i=0; i<10000; i++) {
            dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
            self.num++;
            dispatch_semaphore_signal(sem);
            NSLog(@"%d",self.num);
        }
    });
    
    dispatch_async(queue, ^{
        for (int i=0; i<10000; i++) {
            dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
            self.num++;
            dispatch_semaphore_signal(sem);
            NSLog(@"%d",self.num);
        }
    });
//   这样就能打印到20000,如果不加锁中间可能会有同时访问拿到同样的值进行操作,这样得到的最终结果就不一定是20000,线程安全。
//    同时信号量也能控制开辟线程的数量,例如上面的代码我们可以设置信号量为2。可以开辟2个线程进行处理。

 

Analysis of interview questions

1、

    dispatch_queue_t queue = dispatch_queue_create("liujilou", DISPATCH_QUEUE_SERIAL);
    NSLog(@"1");
    dispatch_async(queue, ^{
        NSLog(@"2");
        dispatch_sync(queue, ^{
            NSLog(@"3");
        });
        //        NSLog(@"4");
    });
    NSLog(@"5");

Deadlock. 152 performs normal printing. Next is a sync, sync words will block threads to execute. But put behind this sync block is a 4, followed by the need to perform isochronous block 3.4 executed, block 3 which has a task, a task added team went 3. 3 is the block has completed execution block. Because it is synchronous serial, will not open a new thread, so the FIFO principle need to wait 4 block is executed, block 3 needs to be performed, but they need to wait 4 3 execution, causing a deadlock.
     Even commented 4 task remains deadlocked. Why inside, because the synchronization function first added to the queue, the task 3 is added to the queue. Task 3 need to wait executing the synchronized function to perform, but the task synchronization functions need to be considered 3 executing the execution is complete. They have formed a mutual wait.
 

2、

dispatch_queue_t queue = dispatch_queue_create("liujilou", DISPATCH_QUEUE_CONCURRENT);
    NSLog(@"1");
    dispatch_async(queue, ^{
        NSLog(@"2");
        dispatch_sync(queue, ^{
            NSLog(@"3");
        });
        NSLog(@"4");
    });
    NSLog(@"5");
    /*
     2020-03-14 01:18:15.206466+0800 filedome[59905:1360188] 1
     2020-03-14 01:18:15.206720+0800 filedome[59905:1360188] 5
     2020-03-14 01:18:15.206845+0800 filedome[59905:1360270] 2
     2020-03-14 01:18:15.206947+0800 filedome[59905:1360270] 3
     2020-03-14 01:18:15.207040+0800 filedome[59905:1360270] 4
     */

     Code is compiled from top to bottom order execution, perform 1, then the asynchronous function does not block the thread will also perform time-consuming so the first 5, then perform 2. Next is a synchronous block the thread, must be executed 3 to perform 4. 

3、

dispatch_queue_t queue = dispatch_queue_create("liujilou", DISPATCH_QUEUE_CONCURRENT);
    NSLog(@"1");
    dispatch_async(queue, ^{
        NSLog(@"2");
        dispatch_async(queue, ^{
            NSLog(@"3");
        });
        NSLog(@"4");
    });
    NSLog(@"5");
    /*
     2020-03-14 01:19:52.246409+0800 filedome[59934:1361575] 1
     2020-03-14 01:19:52.246576+0800 filedome[59934:1361575] 5
     2020-03-14 01:19:52.246611+0800 filedome[59934:1361843] 2
     2020-03-14 01:19:52.246703+0800 filedome[59934:1361843] 4
     2020-03-14 01:19:52.246717+0800 filedome[59934:1361634] 3
     */

     Code is compiled from top to bottom order execution, perform 1, then the asynchronous function does not block the thread will also perform time-consuming so the first 5, then perform 2. Next is an asynchronous empathy performed first four and then 3. The implementation of

4,

dispatch_queue_t queue = dispatch_queue_create("com.liujilou.queue", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(queue, ^{
        NSLog(@"1");
    });
    dispatch_async(queue, ^{
        NSLog(@"2");
    });
    dispatch_sync(queue, ^{
        NSLog(@"3");
    });
    NSLog(@"0");
    dispatch_async(queue, ^{
        NSLog(@"7");
    });
    dispatch_async(queue, ^{
        NSLog(@"8");
    });
    dispatch_async(queue, ^{
        NSLog(@"9");
    });
    /*
     2020-03-14 01:27:51.772658+0800 filedome[60051:1366298] 3
     2020-03-14 01:27:51.772671+0800 filedome[60051:1366397] 1
     2020-03-14 01:27:51.772676+0800 filedome[60051:1366395] 2
     2020-03-14 01:27:51.772784+0800 filedome[60051:1366298] 0
     2020-03-14 01:27:51.772906+0800 filedome[60051:1366396] 9
     2020-03-14 01:27:51.772889+0800 filedome[60051:1366395] 7
     2020-03-14 01:27:51.772920+0800 filedome[60051:1366397] 8
     */

     The result will be more, but there are several value of the order is fixed. 3 are synchronized so that the back of the 3 0 to wait before executing the execution, the latter three asynchronous execution to wait 0 then finished.
     123 is not necessarily in this order of three, 30 fixed sequence. 789 order does not necessarily, but certainly after 0. And many more as long as these conditions are met are correct.
  

 

 

Published 83 original articles · won praise 12 · views 180 000 +

Guess you like

Origin blog.csdn.net/shengdaVolleyball/article/details/104880766