GCD 信号量 dispatch_semaphore

2020-11-10  本文已影响0人  Cwwng

1、理解

GCD中的信号量是指 Dispatch Semaphore,是持有计数的信号。
当计数=0时等待,不可通过。
当计数>=1时,计数减1且不等待,可通过。

dispatch_semaphore_create:创建并初始化信号的总量。
dispatch_semaphore_signal:发送一个信号,让信号总量加1。
dispatch_semaphore_wait:使总信号量减1,当信号总量为0时就等待(阻塞所在线程)。

2、信号量用途

1、控制最大并发量。
2、保持线程同步,将异步执行任务转换为同步执行任务。
3、保证线程安全,为线程加锁。

3、控制最大并发量

    // 控制并发队列中,任务的最大并发量为5
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(5);
    dispatch_queue_t queue = dispatch_queue_create("cwwng-queue", DISPATCH_QUEUE_CONCURRENT);
    for (int i=0; i<100; i++) {
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        dispatch_async(queue, ^{
            NSLog(@"开始 ---- %d %@", i, [NSThread currentThread]);
            sleep(4);
            NSLog(@"结束 ++++ %d %@", i, [NSThread currentThread]);
            dispatch_semaphore_signal(semaphore);
        });
    }
2020-11-09 17:22:03.510667+0800 Demo[50332:2567090] 开始 ---- 2 <NSThread: 0x600003bad1c0>{number = 5, name = (null)}
2020-11-09 17:22:03.510669+0800 Demo[50332:2567093] 开始 ---- 0 <NSThread: 0x600003be3680>{number = 4, name = (null)}
2020-11-09 17:22:03.510667+0800 Demo[50332:2567091] 开始 ---- 1 <NSThread: 0x600003bdbc40>{number = 3, name = (null)}
2020-11-09 17:22:03.510669+0800 Demo[50332:2567089] 开始 ---- 3 <NSThread: 0x600003ba8dc0>{number = 6, name = (null)}
2020-11-09 17:22:03.510977+0800 Demo[50332:2567092] 开始 ---- 4 <NSThread: 0x600003bad540>{number = 7, name = (null)}
2020-11-09 17:22:07.512876+0800 Demo[50332:2567093] 结束 ++++ 0 <NSThread: 0x600003be3680>{number = 4, name = (null)}
2020-11-09 17:22:07.512876+0800 Demo[50332:2567089] 结束 ++++ 3 <NSThread: 0x600003ba8dc0>{number = 6, name = (null)}
2020-11-09 17:22:07.512876+0800 Demo[50332:2567090] 结束 ++++ 2 <NSThread: 0x600003bad1c0>{number = 5, name = (null)}
2020-11-09 17:22:07.512876+0800 Demo[50332:2567091] 结束 ++++ 1 <NSThread: 0x600003bdbc40>{number = 3, name = (null)}
2020-11-09 17:22:07.512930+0800 Demo[50332:2567092] 结束 ++++ 4 <NSThread: 0x600003bad540>{number = 7, name = (null)}
2020-11-09 17:22:07.513148+0800 Demo[50332:2567089] 开始 ---- 5 <NSThread: 0x600003ba8dc0>{number = 6, name = (null)}
2020-11-09 17:22:07.513153+0800 Demo[50332:2567090] 开始 ---- 6 <NSThread: 0x600003bad1c0>{number = 5, name = (null)}
2020-11-09 17:22:07.513182+0800 Demo[50332:2567091] 开始 ---- 7 <NSThread: 0x600003bdbc40>{number = 3, name = (null)}
2020-11-09 17:22:07.513212+0800 Demo[50332:2567092] 开始 ---- 8 <NSThread: 0x600003bad540>{number = 7, name = (null)}
2020-11-09 17:22:07.513459+0800 Demo[50332:2567088] 开始 ---- 9 <NSThread: 0x600003ba5fc0>{number = 8, name = (null)}

4、保持线程同步

    // 将并发队列中,任务的最大并发量为1
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
    dispatch_queue_t queue = dispatch_queue_create("cwwng-queue", DISPATCH_QUEUE_CONCURRENT);
    for (int i=0; i<100; i++) {
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        dispatch_async(queue, ^{
            NSLog(@"开始 ---- %d %@", i, [NSThread currentThread]);
            sleep(4);
            NSLog(@"结束 ++++ %d %@", i, [NSThread currentThread]);
            dispatch_semaphore_signal(semaphore);
        });
    }
2020-11-09 17:24:22.037069+0800 Demo[50433:2569877] 开始 ---- 0 <NSThread: 0x600002ecea80>{number = 3, name = (null)}
2020-11-09 17:24:26.038963+0800 Demo[50433:2569877] 结束 ++++ 0 <NSThread: 0x600002ecea80>{number = 3, name = (null)}
2020-11-09 17:24:26.039298+0800 Demo[50433:2569877] 开始 ---- 1 <NSThread: 0x600002ecea80>{number = 3, name = (null)}
2020-11-09 17:24:30.044625+0800 Demo[50433:2569877] 结束 ++++ 1 <NSThread: 0x600002ecea80>{number = 3, name = (null)}
2020-11-09 17:24:30.045239+0800 Demo[50433:2569877] 开始 ---- 2 <NSThread: 0x600002ecea80>{number = 3, name = (null)}
2020-11-09 17:24:34.050135+0800 Demo[50433:2569877] 结束 ++++ 2 <NSThread: 0x600002ecea80>{number = 3, name = (null)}
2020-11-09 17:24:34.050509+0800 Demo[50433:2569877] 开始 ---- 3 <NSThread: 0x600002ecea80>{number = 3, name = (null)}

5、保证线程安全

信号量的值设置为1,保证多线程访问安全。

- (void)viewDidLoad {
    [super viewDidLoad];
    
    semaphore = dispatch_semaphore_create(1);
    dispatch_queue_t queue1 = dispatch_queue_create("cwwng-queue1", DISPATCH_QUEUE_CONCURRENT);
    dispatch_queue_t queue2 = dispatch_queue_create("cwwng-queue2", DISPATCH_QUEUE_CONCURRENT);
    
    self.nums = 50;
    
    __weak typeof(self) weakSelf = self;
    dispatch_async(queue1, ^{
        [weakSelf testAction];
    });
    
    dispatch_async(queue2, ^{
        [weakSelf testAction];
    });
}

- (void)testAction {
    while (1) {
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        if (self.nums > 0) {
            self.nums--;
            NSLog(@"%@", [NSString stringWithFormat:@"倒计时:%d 线程:%@", self.nums, [NSThread currentThread]]);
            sleep(2);
            dispatch_semaphore_signal(semaphore);
        } else {
            NSLog(@"倒计时结束");
            break;
        }
    }
}
上一篇下一篇

猜你喜欢

热点阅读