iOS - 多线程-读写安全 iOS - 多线程-读写安全

iOS - 多线程-读写安全

假设有一个文件,A线程进行读取操作,B线程进行写入操作,那是非常危险的事情,会造成数据错乱

此时可能会对其进行加锁来保证线程同步

虽然加锁可以解决问题,但是针对该场景,操作其实不会影响原数据,因此是可以允许多线程同时读,以提高性能

其实就是实现多读单写的操作

  1. 多读单写

1.1 场景

  • 同一时间,只能1个线程进行的操作
  • 同一时间,允许多个线程进行的操作
  • 同意时间,不允许即有的操作,又有的操作

1.2 实现方案

1.2.1 pthread_rwlock:读写锁

  • 等待锁的线程会进入休眠

1.2.1.1 示例
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
scss复制代码#import "ViewController.h"
#import <pthread.h>

@interface ViewController ()

@property (nonatomic, assign) pthread_rwlock_t lock;

@end

@implementation ViewController

- (void)viewDidLoad {
[super viewDidLoad];

self.title = @"pthread_rwlock_t";

// 初始化锁
pthread_rwlock_init(&_lock, NULL);
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
for (int i = 0; i < 5; i++) {
dispatch_async(queue, ^{
[self read];
});

dispatch_async(queue, ^{
[self read];
});

dispatch_async(queue, ^{
[self write];
});

dispatch_async(queue, ^{
[self write];
});
}
}

- (void)read {
pthread_rwlock_rdlock(&_lock);

sleep(1);
NSLog(@"%s", __func__);

pthread_rwlock_unlock(&_lock);
}

- (void)write {
pthread_rwlock_wrlock(&_lock);

sleep(1);
NSLog(@"%s", __func__);

pthread_rwlock_unlock(&_lock);
}

@end

执行结果:

可以看到,的操作是连续的,的操作是间隔的

1.2.2 dispatch_barrier_async:异步栅栏调用

  • 这个函数传入的并发队列必须是自己通过dispatch_queue_cretate创建的
  • 如果传入的是一个串行或是一个全局并发队列,那这个函数便等同于dispatch_async函数的效果

可以理解为,每个操作都使用栅栏将其与其它线程隔离开

1.2.2.1 示例
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
33
34
35
36
37
38
39
40
41
42
43
44
45
objectivec复制代码#import "ViewController_barrier.h"

@interface ViewController_barrier ()

@property (nonatomic, strong) dispatch_queue_t queue;

@end

@implementation ViewController_barrier

- (void)viewDidLoad {
[super viewDidLoad];

self.title = @"dispatch_barrier_sync";

self.queue = dispatch_queue_create("rw_queue", DISPATCH_QUEUE_CONCURRENT);
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
for (int i = 0; i < 5; i++) {
[self read];

[self read];

[self write];

[self write];
}
}

- (void)read {
dispatch_async(self.queue, ^{
sleep(1);
NSLog(@"%s", __func__);
});
}

- (void)write {
dispatch_barrier_sync(self.queue, ^{
sleep(1);
NSLog(@"%s", __func__);
});
}

@end

打印结果:

同样达到多读单写的效果

@oubijiexi

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%