GCD(用法三)

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] {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---{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] {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==={number = 4, name = (null)}

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

2018-11-26 16:38:38.125641+0800 OC-Swift[6970:125265] 333==={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==={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(用法三))