美文网首页
GCD(用法三)

GCD(用法三)

作者: gpylove | 来源:发表于2018-11-26 17:16 被阅读7次

    GCD 信号量:dispatch_semaphore

    信号量:就是一种可用来控制访问资源的数量的标识,设定了一个信号量,在线程访问之前,加上信号量的处理,则可告知系统按照我们指定的信号量数量来执行多个线程。

    Dispatch Semaphore 在实际开发中主要用于:

    保持线程同步,将异步执行任务转换为同步执行任务;保证线程安全,为线程加锁。

    Dispatch Semaphore提供了三个函数。

    dispatch_semaphore_create(long value):这个函数是创建一个dispatch_semaphore_类型的信号量,并且创建的时候需要指定信号量的大小。这里的传入的参数value必须大于或等于0,否则dispatch_semaphore_create会返回NULL。

    dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout):等待信号量。如果信号量值为0,那么该函数就会一直等待,也就是不返回(相当于阻塞当前线程),直到该函数等待的信号量的值大于等于1,该函数会对信号量的值进行减1操作,然后返回。

    dispatch_semaphore_signal(dispatch_semaphore_t deem):发送信号量。该函数会对信号量的值进行加1操作。

    注意:通常等待信号量和发送信号量的函数是成对出现的。

    - (void)semaphoreSync {

        NSLog(@"%@",[NSThread currentThread]);

        NSLog(@"begin");

        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);

        dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);

        __blockintnumber =0;

        dispatch_async(queue, ^{

            number =100;

            // 追加任务1

            [NSThread sleepForTimeInterval:1];

            // 模拟耗时操作

            NSLog(@"1---%@",[NSThread currentThread]);

            // 打印当前线程number =100;

            dispatch_semaphore_signal(semaphore);

        });

        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);

        NSLog(@"end");

        NSLog(@"number = %d",number);

    }

    输出结果:

    2018-11-26 16:23:43.813788+0800 OC-Swift[6798:117982] <NSThread: 0x600001dd1400>{number = 1, name = main}

    2018-11-26 16:23:43.813930+0800 OC-Swift[6798:117982] begin

    2018-11-26 16:23:44.814834+0800 OC-Swift[6798:118028] 1---<NSThread: 0x600001da5640>{number = 3, name = (null)}

    2018-11-26 16:23:44.815409+0800 OC-Swift[6798:117982] end

    2018-11-26 16:23:44.815778+0800 OC-Swift[6798:117982] number = 100

    结果分析:

    这是因为异步执行不会做任何等待,可以继续执行任务。异步执行将任务1追加到队列之后,不做等待,接着执行dispatch_semaphore_wait方法。此时 semaphore == 0,当前线程进入等待状态。然后,异步任务1开始执行。任务1执行到dispatch_semaphore_signal之后,此时 semaphore == 1,dispatch_semaphore_wait方法使总信号量减1,正在被阻塞的线程(主线程)恢复继续执行。最后打印end,number = 100。这样就实现了线程同步,将异步执行任务转换为同步执行任务。

    用GCD的信号量来实现异步线程同步操作

    - (void)semaphore {

        NSLog(@"%@",[NSThread currentThread]);

        NSLog(@"begin");

        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

        dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);

        dispatch_async(queue, ^{

            NSLog(@"111===%@",[NSThread currentThread]);

            dispatch_semaphore_signal(semaphore);

        });

        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);

        dispatch_async(queue, ^{

            NSLog(@"222===%@",[NSThread currentThread]);

            dispatch_semaphore_signal(semaphore);

        });

        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);

        dispatch_async(queue, ^{

            NSLog(@"333===%@",[NSThread currentThread]);

            dispatch_semaphore_signal(semaphore);

        });

        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);

        dispatch_async(dispatch_get_global_queue(0, 0), ^{

            NSLog(@"444===%@",[NSThread currentThread]);

        });

        NSLog(@"end");

    }

    输出结果:

    2018-11-26 16:38:38.125097+0800 OC-Swift[6970:124755] <NSThread: 0x6000020ca980>{number = 1, name = main}

    2018-11-26 16:38:38.125197+0800 OC-Swift[6970:124755] begin

    2018-11-26 16:38:38.125347+0800 OC-Swift[6970:124800] 111===<NSThread: 0x6000020446c0>{number = 4, name = (null)}

    2018-11-26 16:38:38.125490+0800 OC-Swift[6970:124800] 222===<NSThread: 0x6000020446c0>{number = 4, name = (null)}

    2018-11-26 16:38:38.125641+0800 OC-Swift[6970:125265] 333===<NSThread: 0x6000020b7f40>{number = 5, name = (null)}

    2018-11-26 16:38:38.125735+0800 OC-Swift[6970:124755] end

    2018-11-26 16:38:38.125763+0800 OC-Swift[6970:125265] 444===<NSThread: 0x6000020b7f40>{number = 5, name = (null)}

    结果分析:

    使用信号量实现异步线程同步操作时,虽然任务是一个接一个被同步执行的,但因为是在并发队列,并不是所有的任务都是在同一个线程执行的。这有别于异步函数+串行队列的方式(异步函数+ 串行队列的方式中,所有的任务都是在同一个新线程被串行执行的)。

    后记:

    - (void)groupSemaphore {

        dispatch_group_t group = dispatch_group_create();

        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

        for(inti =0; i <10; i++)

        {

            dispatch_group_enter(group);

            dispatch_group_async(group, queue, ^{

                NSLog(@"%i",i);

                dispatch_group_leave(group);

            });

        }

        dispatch_group_wait(group, DISPATCH_TIME_FOREVER);

        NSLog(@"end");

    }

    输出结果:

    2018-11-26 17:10:17.422095+0800 OC-Swift[7408:141478] 2

    2018-11-26 17:10:17.422100+0800 OC-Swift[7408:141472] 0

    2018-11-26 17:10:17.422103+0800 OC-Swift[7408:141477] 3

    2018-11-26 17:10:17.422106+0800 OC-Swift[7408:141479] 1

    2018-11-26 17:10:17.422280+0800 OC-Swift[7408:141479] 4

    2018-11-26 17:10:17.422280+0800 OC-Swift[7408:141478] 5

    2018-11-26 17:10:17.422286+0800 OC-Swift[7408:141472] 6

    2018-11-26 17:10:17.422295+0800 OC-Swift[7408:141477] 7

    2018-11-26 17:10:17.422354+0800 OC-Swift[7408:141479] 8

    2018-11-26 17:10:17.422359+0800 OC-Swift[7408:141478] 9

    2018-11-26 17:10:17.422801+0800 OC-Swift[7408:141430] end

    - (void)groupSemaphore {

        dispatch_group_t group = dispatch_group_create();

        dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);

        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

        for(inti =0; i <10; i++)

        {

            dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);

            dispatch_group_async(group, queue, ^{

                NSLog(@"%i",i);

                dispatch_semaphore_signal(semaphore);

            });

        }

        dispatch_group_wait(group, DISPATCH_TIME_FOREVER);

        NSLog(@"end");

    }

    输出结果:

    2018-11-26 17:11:39.722899+0800 OC-Swift[7433:142403] 0

    2018-11-26 17:11:39.723046+0800 OC-Swift[7433:142403] 1

    2018-11-26 17:11:39.723149+0800 OC-Swift[7433:142403] 2

    2018-11-26 17:11:39.723227+0800 OC-Swift[7433:142403] 3

    2018-11-26 17:11:39.723304+0800 OC-Swift[7433:142403] 4

    2018-11-26 17:11:39.723381+0800 OC-Swift[7433:142403] 5

    2018-11-26 17:11:39.723465+0800 OC-Swift[7433:142404] 6

    2018-11-26 17:11:39.723554+0800 OC-Swift[7433:142404] 7

    2018-11-26 17:11:39.723637+0800 OC-Swift[7433:142404] 8

    2018-11-26 17:11:39.723724+0800 OC-Swift[7433:142404] 9

    2018-11-26 17:11:39.723799+0800 OC-Swift[7433:142371] end

    两段代码结果对比,他们都确保了dispatch_group_wait最后执行,但是第一段是异步执行的,第二段是顺序执行的。dispatch_semaphore实现了异步线程同步操作。

    相关文章

      网友评论

          本文标题:GCD(用法三)

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