读写锁是计算机程序的并发控制的一种同步机制,也称“共享-互斥锁”、多读者-单写者锁。读操作可并发重入,写操作是互斥的。
使用两把互斥锁与一个整数计数器实现。计数器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]; }); } 复制代码
以上就是关于读写锁的实现原理以及它的一些使用方式。如果你有更好的实现方式,欢迎私信我。