GCD同步任务实现加锁效果

1、DISPATCH_QUEUE_SERIAL
1.1、串行队列使队列中的任务同步执行,单次只能执行一个任务
1.2、示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#import "ViewController.h"
#import <pthread.h>
@implementation ViewController
static NSUInteger ticketCount_ = 20;
- (void)viewDidLoad
{
    [super viewDidLoad];
    dispatch_queue_t queue = dispatch_queue_create("com.yusian.custom-queue", DISPATCH_QUEUE_SERIAL);
    for (int i = 0; i < 5; i++) {
        dispatch_async(queue, ^{
            [self saleTicket];
        });
    }
}
- (void)saleTicket
{
    NSUInteger remain = ticketCount_;
    sleep(1);
    ticketCount_ = --remain;
    NSLog(@"%ld, %@", ticketCount_, [NSThread currentThread]);
}
@end

执行结果:

2018-11-27 21:45:13.668026+0800 MultiThread[1652:65435] 19, <NSThread: 0x60000349d340>{number = 3, name = (null)}
2018-11-27 21:45:14.670487+0800 MultiThread[1652:65435] 18, <NSThread: 0x60000349d340>{number = 3, name = (null)}
2018-11-27 21:45:15.674636+0800 MultiThread[1652:65435] 17, <NSThread: 0x60000349d340>{number = 3, name = (null)}
2018-11-27 21:45:16.678230+0800 MultiThread[1652:65435] 16, <NSThread: 0x60000349d340>{number = 3, name = (null)}
2018-11-27 21:45:17.683553+0800 MultiThread[1652:65435] 15, <NSThread: 0x60000349d340>{number = 3, name = (null)}

2、dispatch_semaphore
2.1、dispatch_semaphore(dispatch:派遣、调度,semaphore:信号量)
2.2、dispatch_semaphore的作用是限制gcd的最大并发量,如果为1则类似同步效果
2.3、示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#import "ViewController.h"
#import <pthread.h>
@interface ViewController()
{
    dispatch_semaphore_t    _semaphore;
}
@end
@implementation ViewController
static NSUInteger ticketCount_ = 20;
- (void)viewDidLoad
{
    [super viewDidLoad];
    // 如果参数为5则同时执行5条线程,如果为1,则每次只有一条线程
    _semaphore = dispatch_semaphore_create(1);
    for (int i = 0; i < 10; i++) {
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
            [self saleTicket];
        });
    }
}
- (void)saleTicket
{
    // 第二个参数的超时时间,超过超时时间则直接执行,不再等待,DISPATCH_TIME_FOREVER为一直等待
    dispatch_semaphore_wait(_semaphore, DISPATCH_TIME_FOREVER);
    NSUInteger remain = ticketCount_;
    sleep(1);
    ticketCount_ = --remain;
    NSLog(@"%ld", ticketCount_);
    // 执行结束后发送信号释放线程占用
    dispatch_semaphore_signal(_semaphore);
}
@end

执行结果:

2018-11-27 21:14:58.762370+0800 MultiThread[1269:34401] 19
2018-11-27 21:14:59.766374+0800 MultiThread[1269:34404] 18
2018-11-27 21:15:00.770787+0800 MultiThread[1269:34402] 17
2018-11-27 21:15:01.771741+0800 MultiThread[1269:34403] 16
2018-11-27 21:15:02.773284+0800 MultiThread[1269:34412] 15
2018-11-27 21:15:03.777777+0800 MultiThread[1269:34416] 14
2018-11-27 21:15:04.782864+0800 MultiThread[1269:34417] 13
2018-11-27 21:15:05.787534+0800 MultiThread[1269:34418] 12
2018-11-27 21:15:06.792096+0800 MultiThread[1269:34419] 11
2018-11-27 21:15:07.794997+0800 MultiThread[1269:34420] 10

3、dispatch_group_notify
3.1、如果需要先执行A、B,再执行C,该如何实现;
3.2、先将A、B加入到一个并行队列组dispatch_group;
3.3、C通过dispatch_group_notify等待A、B结束后被唤醒执行
3.4、示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#import "ViewController.h"
#import <pthread.h>
@implementation ViewController
- (void)viewDidLoad
{
    [super viewDidLoad];
    dispatch_group_t group = dispatch_group_create();
    dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);
    dispatch_group_async(group, queue, ^{
        [self methodA];
    });
    dispatch_group_async(group, queue, ^{
        [self methodB];
    });
    // 等待线程结束后被唤醒执行
    dispatch_group_notify(group, queue, ^{
        [self methodC];
    });
}
- (void)methodA
{
    NSLog(@"---a---");
}
- (void)methodB
{
    NSLog(@"---b---");
    sleep(2);
}
- (void)methodC
{
    NSLog(@"---c---");
}

执行结果:

2018-11-27 21:51:51.798390+0800 MultiThread[1774:73287] ---a---
2018-11-27 21:51:51.798393+0800 MultiThread[1774:73288] ---b---
2018-11-27 21:51:53.803127+0800 MultiThread[1774:73288] ---c---

Leave a Reply