对IOS GCD的理解

提到IOS的多线程,很多人会想到GCD。确实,线程只是GCD其中一部分,它还包括队列,同步,异步等。正因为有几种类型的组合,很多人都比较容易混淆。相信很多人用得比较多的只是:

//使用子线程
dispatch_async(dispatch_get_global_queue(0, 0), ^{
           //子线程的操作
 });

把队列和同异步分开来,就比较好理解:
队列:所有要处理的事件,一个个放到队列里面。根据出列方式的不同,又分为串行队列和并行队列。
串行队列(DISPATCH_QUEUE_SERIAL):是处理完一个事件再出列一个事件。
并行队列(DISPATCH_QUEUE_CONCURRENT):是队列的所有事件一起出来。
同步(sync):会等待处理事件的结果,所以会阻塞当前的线程,不会产生新的子线程。
异步(async):不等待事件的结果,不会阻塞当前线程,会产生新的子线程。

为了更好理解,我做了以下的测试:

1、同步+串行队列

- (void)testThreed1:(NSInteger)tag
{
    NSLog(@">>>>>>>>>threed%zi start",tag);
    dispatch_sync(_serialQueue, ^{

        NSLog(@">>>>>>>>>threed%zi ining isMain=%d",tag,[NSThread currentThread].isMainThread);
        sleep(3);
    });
    NSLog(@">>>>>>>>>threed%zi end",tag);
}

- (void)testSync
{
    for(NSInteger i = 0;i<3;i++)
    {
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
            [self testThreed1:i];
        });
    }
    NSLog(@">>>>>>>>end all");
}

执行testSync,结果如下:

2018-08-17 15:41:31.325182+0800 SummaryTest[3324:2499801] >>>>>>>>end all
2018-08-17 15:41:31.325274+0800 SummaryTest[3324:2499905] >>>>>>>>>threed0 start
2018-08-17 15:41:31.325496+0800 SummaryTest[3324:2499905] >>>>>>>>>threed0 ining isMain=0
2018-08-17 15:41:31.325751+0800 SummaryTest[3324:2499913] >>>>>>>>>threed1 start
2018-08-17 15:41:31.337699+0800 SummaryTest[3324:2499906] >>>>>>>>>threed2 start
2018-08-17 15:41:34.330605+0800 SummaryTest[3324:2499905] >>>>>>>>>threed0 end
2018-08-17 15:41:34.330933+0800 SummaryTest[3324:2499913] >>>>>>>>>threed1 ining isMain=0
2018-08-17 15:41:37.336189+0800 SummaryTest[3324:2499913] >>>>>>>>>threed1 end
2018-08-17 15:41:37.336529+0800 SummaryTest[3324:2499906] >>>>>>>>>threed2 ining isMain=0
2018-08-17 15:41:40.338447+0800 SummaryTest[3324:2499906] >>>>>>>>>threed2 end

testSync函数中通过3个异步操作,为的是能尽量同时往串行队列_serialQueue添加事件。然后,给同步处理先入队列的那个事件threed0 ining,处理完成后,下一个事件再出来。所以得到上面的结果。

2、异步+串行队列

- (void)testThreed1:(NSInteger)tag
{
    NSLog(@">>>>>>>>>threed%zi start",tag);
    dispatch_async(_serialQueue, ^{

        NSLog(@">>>>>>>>>threed%zi ining isMain=%d",tag,[NSThread currentThread].isMainThread);
        sleep(3);
    });
    NSLog(@">>>>>>>>>threed%zi end",tag);
}
- (void)testSync
{
    for(NSInteger i = 0;i<3;i++)
    {
//        dispatch_async(dispatch_get_global_queue(0, 0), ^{
//            [self testThreed1:i];
//        });
        [self testThreed1:i];
    }
    NSLog(@">>>>>>>>end all");
}

结果如下:
2018-08-17 15:50:55.405933+0800 SummaryTest[3327:2501210] >>>>>>>>>threed0 start
2018-08-17 15:50:55.406064+0800 SummaryTest[3327:2501210] >>>>>>>>>threed0 end
2018-08-17 15:50:55.406121+0800 SummaryTest[3327:2501210] >>>>>>>>>threed1 start
2018-08-17 15:50:55.406181+0800 SummaryTest[3327:2501210] >>>>>>>>>threed1 end
2018-08-17 15:50:55.406176+0800 SummaryTest[3327:2501264] >>>>>>>>>threed0 ining isMain=0
2018-08-17 15:50:55.406233+0800 SummaryTest[3327:2501210] >>>>>>>>>threed2 start
2018-08-17 15:50:55.406290+0800 SummaryTest[3327:2501210] >>>>>>>>>threed2 end
2018-08-17 15:50:55.406338+0800 SummaryTest[3327:2501210] >>>>>>>>end all
2018-08-17 15:50:58.410209+0800 SummaryTest[3327:2501264] >>>>>>>>>threed1 ining isMain=0
2018-08-17 15:51:01.415635+0800 SummaryTest[3327:2501264] >>>>>>>>>threed2 ining isMain=0

因为不阻塞了,所以testSync中,我没通过异步添加队列了,不阻塞,循环完成后,队列就添加了3个事件。

3、同步+并行队列

- (void)testThreed1:(NSInteger)tag
{
    NSLog(@">>>>>>>>>threed%zi start",tag);
    dispatch_sync(_concurrentQueue, ^{
        NSLog(@">>>>>>>>>threed%zi ining",tag);
        sleep(2);
    });
    NSLog(@">>>>>>>>>threed%zi end",tag);
}
- (void)testSync
{
    for(NSInteger i = 0;i<3;i++)
    {
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
            [self testThreed1:i];
        });
    }
    NSLog(@">>>>>>>>end all");
}

结果如下:
2018-08-17 15:56:43.414786+0800 SummaryTest[3329:2502039] >>>>>>>>end all
2018-08-17 15:56:43.416005+0800 SummaryTest[3329:2502106] >>>>>>>>>threed0 start
2018-08-17 15:56:43.416130+0800 SummaryTest[3329:2502106] >>>>>>>>>threed0 ining
2018-08-17 15:56:43.416294+0800 SummaryTest[3329:2502105] >>>>>>>>>threed1 start
2018-08-17 15:56:43.416354+0800 SummaryTest[3329:2502105] >>>>>>>>>threed1 ining
2018-08-17 15:56:43.416573+0800 SummaryTest[3329:2502104] >>>>>>>>>threed2 start
2018-08-17 15:56:43.416635+0800 SummaryTest[3329:2502104] >>>>>>>>>threed2 ining
2018-08-17 15:56:45.417930+0800 SummaryTest[3329:2502105] >>>>>>>>>threed1 end
2018-08-17 15:56:45.418025+0800 SummaryTest[3329:2502106] >>>>>>>>>threed0 end
2018-08-17 15:56:45.418245+0800 SummaryTest[3329:2502104] >>>>>>>>>threed2 end

可见,2秒后,线程0,1,2几乎是同时结束,说明他们是同时进行处理的。

4、异步+并行

这个就不分析了,平时用的最多。

所以,对于队列和同异步,不要混淆,两个是独立的,相互不影响的。不管你是什么队列,我是同步的,就一直是同步,一直都是阻塞当前线程。

死锁的情况

- (void)deadLock
{
    //来个死锁的
    NSLog(@">>>>>>>>>start");
    dispatch_sync(dispatch_get_main_queue(), ^{
        NSLog(@">>>>>>>>>>in");
    });
    NSLog(@">>>>>>>>>>end");
}

你可以分析出来原因的。

你可能感兴趣的:(对IOS GCD的理解)