美文网首页
GCD 信号量 dispatch_semaphore

GCD 信号量 dispatch_semaphore

作者: Cwwng | 来源:发表于2020-11-10 00:05 被阅读0次

    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;
            }
        }
    }
    

    相关文章

      网友评论

          本文标题:GCD 信号量 dispatch_semaphore

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