1、读写规则

同一时间,只能有1个线程进行写的操作
同一时间,允许有多个线程进行读的操作
同一时间,不允许既有写的操作,又有读的操作
如果使用普通的同步方案,比如用信号量保证只有一个线程进行read、write操作:

  1. - (void)read {
  2. dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
  3. NSLog(@"%s", __func__);
  4. dispatch_semaphore_signal(self.semaphore);
  5. }
  6. - (void)write {
  7. dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER);
  8. NSLog(@"%s", __func__);
  9. dispatch_semaphore_signal(self.semaphore);
  10. }

这样就会造成每次只有一个线程可以进行read操作,效率很低,如果不给read加锁,就有可能造成read和write同时进行。所有普通的同步方案不适合读写操作。

2、pthread_rwlock_t(读写锁)

pthread_rwlock_t是专门用于读写安全的锁
有如下API:

  1. - (void)rwlockAPI {
  2. // 初始化
  3. pthread_rwlock_t lock;
  4. pthread_rwlock_init(&lock, NULL);
  5. // 读-加锁
  6. pthread_rwlock_rdlock(&lock);
  7. // 读-尝试加锁
  8. pthread_rwlock_tryrdlock(&lock);
  9. // 写-加锁
  10. pthread_rwlock_wrlock(&lock);
  11. // 写-尝试加锁
  12. pthread_rwlock_trywrlock(&lock);
  13. // 解锁
  14. pthread_rwlock_unlock(&lock);
  15. // 销毁
  16. pthread_rwlock_destroy(&lock);
  17. }

应用举例:

  1. - (void)read {
  2. pthread_rwlock_rdlock(&_lock);
  3. NSLog(@"%s", __func__);
  4. sleep(1);
  5. pthread_rwlock_unlock(&_lock);
  6. }
  7. - (void)write {
  8. pthread_rwlock_wrlock(&_lock);
  9. NSLog(@"%s", __func__);
  10. sleep(1);
  11. pthread_rwlock_unlock(&_lock);
  12. }

3、dispatch_barrier_async(栅栏函数)

这个函数传入的并发队列必须是自己通过dispatch_queue_cretate创建的,如果传入的是一个串行或是一个全局的并发队列,那这个函数便等同于dispatch_async函数的效果。
当执行任务时会建立栅栏,屏蔽其他线程,比如写入操作使用dispatch_barrier_async调用,读取操作使用dispatch_async调用,来实现多读单写的效果:

  1. - (void)read {
  2. dispatch_async(self.queue, ^{
  3. NSLog(@"%s", __func__);
  4. sleep(1);
  5. });
  6. }
  7. - (void)write {
  8. dispatch_barrier_async(self.queue, ^{
  9. NSLog(@"%s", __func__);
  10. sleep(1);
  11. });
  12. }

执行效果如下:
image.png