iOS进阶

iOS 原理探究-读写锁

2020-03-07  本文已影响0人  Joker_King

读写锁是计算机程序的并发控制的一种同步机制,也称“共享-互斥锁”、多读者-单写者锁。读操作可并发重入,写操作是互斥的。

实现原理

两把互斥锁

使用两把互斥锁与一个整数计数器实现。计数器condition跟踪被阻塞的读线程。互斥锁rlock保护condition,供读者使用。互斥锁wlock 确保写操作互斥。

#import "JKRWLock.h"
#import <pthread/pthread.h>

pthread_mutex_t rlock = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t wlock = PTHREAD_MUTEX_INITIALIZER;

static int condition = 0;

@implementation JKRWLock
//读者加锁
- (void)rLock {
    pthread_mutex_lock(&rlock);
    condition++;
    if (condition == 1) {
        pthread_mutex_lock(&wlock);
    }
    pthread_mutex_unlock(&rlock);
}
//读者解锁
- (void)rUnlock {
    pthread_mutex_lock(&rlock);
    condition--;
    if (condition == 0) {
        pthread_mutex_unlock(&wlock);
    }
    pthread_mutex_unlock(&rlock);
}
//写者加锁
- (void)wLock {
    pthread_mutex_lock(&wlock);
}
//写者解锁
- (void)wUnlock {
    pthread_mutex_unlock(&wlock);
}
@end

条件变量+互斥锁

可使用条件变量cond与普通的互斥锁rwlock、整型计数器readCount(表示正在读的个数)与布尔标志write(表示正在写)来实现读写锁。

#import "JKRWLock.h"
#import <pthread/pthread.h>

@interface JKRWLock ()
@property (nonatomic, assign) int readCount;
@property (nonatomic, assign, getter=isWriting) BOOL write;
@end
//读写锁
pthread_mutex_t rwlock = PTHREAD_MUTEX_INITIALIZER;
//条件变量
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

@implementation JKRWLock

//读者加锁
- (void)rLock {
    pthread_mutex_lock(&rwlock);
    while (self.isWriting) {
        pthread_cond_wait(&cond, &rwlock);
    }
    self.readCount++;
    pthread_mutex_unlock(&rwlock);
}
//读者解锁
- (void)rUnlock {
   pthread_mutex_lock(&rwlock);
    self.readCount--;
   if (self.readCount == 0) {
       //唤起一条写的线程
       pthread_cond_signal(&cond);
   }
   pthread_mutex_unlock(&rwlock);
}
//写者加锁
- (void)wLock {
    pthread_mutex_lock(&rwlock);
    while (self.isWriting || self.readCount > 0) {
        pthread_cond_wait(&cond, &rwlock);
    }
    self.write = YES;
    pthread_mutex_unlock(&rwlock);
}
//写者解锁
- (void)wUnlock {
    pthread_mutex_lock(&rwlock);
    self.write = NO;
    //唤起多个读的线程
    pthread_cond_broadcast(&cond);
    pthread_mutex_unlock(&rwlock);
}
@end

同步任务+栅栏

读数据

- (id)objectForKey:(NSString *)key {
    __block id obj;
    // 同步读取指定数据:
    dispatch_sync(self.concurrent_queue, ^{
        obj = [self.dataCenterDic objectForKey:key];
    });
    return obj;
}

写数据

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

总结

以上就是关于读写锁的实现原理以及它的一些使用方式。如果你有更好的实现方式,欢迎私信我。

上一篇下一篇

猜你喜欢

热点阅读