为了保证数据读写的安全, 我们可以采用锁, GCD等方案来保证线程安全.
读写安全要保证以下的原则:
1: 读写互斥 同一时间不允许既有读的操作又有些的操作
2:写写互斥 同一时间,只能允许 1 个线程进行写的操作
3:读读并发 允许多个线程同时读取
如何实现:
方案 1:
读写锁-> phread_rwlock
等待锁的线程会进入休眠
常用 api:

Demo: 复制代码可直接运行
//
// ViewController.m
// 读写安全 OC
//
// Created by liuyaozong on 2022/1/24.
//
#import "ViewController.h"
#import <pthread.h>
@interface ViewController ()
@property (nonatomic,strong) dispatch_queue_t queue;
@property (assign,nonatomic) pthread_rwlock_t lock;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.queue = dispatch_queue_create("test_wf", DISPATCH_QUEUE_CONCURRENT);
//初始化读写锁
pthread_rwlock_init(&_lock, NULL);
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
for (int i = 0; i < 10; i ++) {
dispatch_async(self.queue, ^{
[[[NSThread alloc] initWithTarget:self selector:@selector(write) object:nil] start];
});
dispatch_async(self.queue, ^{
[[[NSThread alloc] initWithTarget:self selector:@selector(read) object:nil] start];
});
}
}
//写数据
-(void)write {
pthread_rwlock_wrlock(&_lock);
sleep(1);
NSLog(@"write");
pthread_rwlock_unlock(&_lock);
}
//读数据
-(void)read {
pthread_rwlock_rdlock(&_lock);
sleep(1);
NSLog(@"read");
pthread_rwlock_unlock(&_lock);
}
-(void)dealloc {
pthread_rwlock_destroy(&_lock);
}
@end
方案 2:
dispatch_barrier_async GCD 栅栏
1.这个函数传入的并发队列必须是自己通过 dispatch_queue_create创建的
2.如果传入的是一个串行或是一个全局的并发队列, 那这个函数等同于dispatch_async 函数的效果
主要代码: 详情见 demo 记得 star
//写数据
-(void)write2 {
dispatch_barrier_async(self.queue, ^{
sleep(1);
NSLog(@"write");
});
}
//读数据
-(void)read2 {
dispatch_async(self.queue, ^{
sleep(1);
NSLog(@"read");
});
}
实际效果:

由上图可以看出. 读读几乎是同时出现. 写写 中间相隔的时间相对较长
网友评论