GCD之信号量机制二

时间:2021-09-08 10:00:12

在前面GCD之信号量机制一中介绍了通过信号量设置并行最大线程数,依此信号量还可以防止多线程访问公有变量时数据有误,下面的代码能说明。

1.下面是不采用信号量修改公有变量的值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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);
    __block int count=1000;
    for (int i=0; i<100; i++) {
        //信号量减1,如果同时开启10个以上的线程,则信号量小于等于0,此时就会阻塞该线程。
//        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        dispatch_group_async(group, queue, ^{
            int value = (arc4random() % 4) + 6;
            NSLog(@"%d-%d= %d",count,value,count-value);
            count=count-value;
        //每个线程执行减1后通过信号量通知加1,这样始终保持线程在10个之内
//        dispatch_semaphore_signal(semaphore);
        });
    }
     
    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);

2.运行结果如下:

GCD之信号量机制二

3.声明一个初始值为1的信号量来开启线程修改公有变量时

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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);
   __block int count=1000;
   for (int i=0; i<100; i++) {
       //信号量减1,如果同时开启10个以上的线程,则信号量小于等于0,此时就会阻塞该线程。
       dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
       dispatch_group_async(group, queue, ^{
           int value = (arc4random() % 4) + 6;
           NSLog(@"%d-%d= %d",count,value,count-value);
           count=count-value;
       //每个线程执行减1后通过信号量通知加1,这样始终保持线程在10个之内
       dispatch_semaphore_signal(semaphore);
       });
   }
    
   dispatch_group_wait(group, DISPATCH_TIME_FOREVER);

4.运行结果如下:

GCD之信号量机制二

可以看到,第一代码段时修改公有变量时不是有序的,第二个代码段才是真正正确的修改顺序。这过程可取款的过程一样,金额是1000,可能在不同的地方同时取款,取款时不可能金额是像第一代码段那样。这个和C#的lock关键字有一样的效果。