1、读写规则
同一时间,只能有1个线程进行写的操作
同一时间,允许有多个线程进行读的操作
同一时间,不允许既有写的操作,又有读的操作
如果使用普通的同步方案,比如用信号量保证只有一个线程进行read、write操作:
- (void)read {
dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"%s", __func__);
dispatch_semaphore_signal(self.semaphore);
}
- (void)write {
dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"%s", __func__);
dispatch_semaphore_signal(self.semaphore);
}
这样就会造成每次只有一个线程可以进行read操作,效率很低,如果不给read加锁,就有可能造成read和write同时进行。所有普通的同步方案不适合读写操作。
2、pthread_rwlock_t(读写锁)
pthread_rwlock_t是专门用于读写安全的锁
有如下API:
- (void)rwlockAPI {
// 初始化
pthread_rwlock_t lock;
pthread_rwlock_init(&lock, NULL);
// 读-加锁
pthread_rwlock_rdlock(&lock);
// 读-尝试加锁
pthread_rwlock_tryrdlock(&lock);
// 写-加锁
pthread_rwlock_wrlock(&lock);
// 写-尝试加锁
pthread_rwlock_trywrlock(&lock);
// 解锁
pthread_rwlock_unlock(&lock);
// 销毁
pthread_rwlock_destroy(&lock);
}
应用举例:
- (void)read {
pthread_rwlock_rdlock(&_lock);
NSLog(@"%s", __func__);
sleep(1);
pthread_rwlock_unlock(&_lock);
}
- (void)write {
pthread_rwlock_wrlock(&_lock);
NSLog(@"%s", __func__);
sleep(1);
pthread_rwlock_unlock(&_lock);
}
3、dispatch_barrier_async(栅栏函数)
这个函数传入的并发队列必须是自己通过dispatch_queue_cretate创建的,如果传入的是一个串行或是一个全局的并发队列,那这个函数便等同于dispatch_async函数的效果。
当执行任务时会建立栅栏,屏蔽其他线程,比如写入操作使用dispatch_barrier_async调用,读取操作使用dispatch_async调用,来实现多读单写的效果:
- (void)read {
dispatch_async(self.queue, ^{
NSLog(@"%s", __func__);
sleep(1);
});
}
- (void)write {
dispatch_barrier_async(self.queue, ^{
NSLog(@"%s", __func__);
sleep(1);
});
}
执行效果如下: