iOS 多线程-实现多读单写

西门桃桃 2022-05-18 PM 5147℃ 3条

什么是多读单写?

多个线程同时读一个变量是不需要同步的,而多个线程同时写一个变量或一个线程写而其他线程读某个变量,是需要同步的,可以总结为:“多读不互斥,而读写和多写互斥”。

实现方案:

一、加读写锁 pthread_rwlock 来实现

#import <pthread.h>

@interface FTReadWhiteSafeDic() {
    // 声明一个读写锁
   pthread_rwlock_t  lock;
  // 定义一个并发队列
    dispatch_queue_t concurrent_queue;
    // 用户数据中心, 可能多个线程需要数据访问
    NSMutableDictionary *userCenterDic;
}

@end

// 多读单写模型
@implementation FTReadWhiteSafeDic

- (id)init {
    self = [super init];
    if (self) {
      //初始化读写锁
      pthread_rwlock_init(&lock,NULL);
      // 创建数据容器
       userCenterDic = [NSMutableDictionary dictionary];
      // 通过宏定义 DISPATCH_QUEUE_CONCURRENT 创建一个并发队列
      concurrent_queue = dispatch_queue_create("read_write_queue", DISPATCH_QUEUE_CONCURRENT);
    }
    return self;
}

- (id)objectForKey:(NSString *)key {
    //加读锁
    pthread_rwlock_rdlock(&_rwlock);
    id obj = [userCenterDic objectForKey:key];
    pthread_rwlock_unlock(&_rwlock);
    return obj;
}

- (void)setObject:(id)obj forKey:(NSString *)key {
     //加写锁
    pthread_rwlock_wrlock(&_rwlock);
    [userCenterDic setObject:obj forKey:key];
    pthread_rwlock_unlock(&_rwlock);    
}

二、使用 dispatch_barrie 来实现。

@interface FTReadWhiteSafeDic() {
    // 定义一个并发队列
    dispatch_queue_t concurrent_queue;

    // 用户数据中心, 可能多个线程需要数据访问
    NSMutableDictionary *userCenterDic;
}

@end

// 多读单写模型
@implementation FTReadWhiteSafeDic

- (id)init {
    self = [super init];
    if (self) {
        // 通过宏定义 DISPATCH_QUEUE_CONCURRENT 创建一个并发队列
        concurrent_queue = dispatch_queue_create("read_write_queue", DISPATCH_QUEUE_CONCURRENT);
        // 创建数据容器
        userCenterDic = [NSMutableDictionary dictionary];
    }
    return self;
}

- (id)objectForKey:(NSString *)key {
    __block id obj;
    // 异步读取指定数据
    dispatch_async(concurrent_queue, ^{// dispatch_sync 设置为同步读取
        obj = [userCenterDic objectForKey:key];
    });
    return obj;
}

- (void)setObject:(id)obj forKey:(NSString *)key {
    // 异步栅栏调用设置数据
    dispatch_barrier_async(concurrent_queue, ^{
        [userCenterDic setObject:obj forKey:key];
    });
}

注意点:

  • 读操作 dispatch_asyncdispatch_sync 区别

dispatch_async 并发异步回调方式读取数据,当你对外部调用顺序没有要求时,可以这么调用。

dispatch_sync 并发同步读取数据,能保证外部调用顺序。此时会堵塞当前线程,当前线程需要等待读取任务执行完成,才能继续执行后边代码任务。

标签: 多线程, 线程安全

非特殊说明,本博所有文章均为博主原创。

评论啦~



已有 3 条评论


  1. Deven
    Deven

    (id)objectForKey:(NSString *)key {
    __block id obj;
    // 异步读取指定数据
    dispatch_async(concurrent_queue, ^{// dispatch_sync 设置为同步读取

    obj = [userCenterDic objectForKey:key];

    });
    return obj;
    }

    这里 async 会 返回 nil

    回复 2022-08-12 10:18
  2. vgjqelznen
    vgjqelznen

    兄弟写的非常好 https://www.cscnn.com/

    回复 2024-10-19 14:48
  3. tfuwfkevyk
    tfuwfkevyk

    博主太厉害了!

    回复 2024-11-14 02:43