| 在iOS中,上述代码中的PV原语可以替换成GCD中的信号量API,dispatch_semaphore_t来实现,但是需要额外维护一个readerCount以及实现readerCount互斥访问的信号量,手动实现比较麻烦,封装成统一接口有一定难度。不过好在iOS开发中可以找到现成的读者写者锁: pthread_rwlock_t 这是一个古老的C语言层面的函数,用法如下: // Initialization of lock, pthread_rwlock_t is a value type and must be declared as var in order to refer it later. Make sure not to copy it. var lock = pthread_rwlock_t() pthread_rwlock_init(&lock, nil)  // Protecting read section: pthread_rwlock_rdlock(&lock) // Read shared resource pthread_rwlock_unlock(&lock)  // Protecting write section: pthread_rwlock_wrlock(&lock) // Write shared resource pthread_rwlock_unlock(&lock)  // Clean up pthread_rwlock_destroy(&lock) 
 接口简洁但是却不友好,需要注意pthread_rwlock_t是值类型,用=赋值会直接拷贝,不小心就会浪费内存,另外用完后还需要记得销毁,容易出错,有没有更高级更易用的API呢? GCD barrier dispatch_barrier_async /  dispatch_barrier_sync并不是专门用来解决读者写者问题的,barrier主要用于以下场景:当执行某一任务A时,需要该队列上之前添加的所有操作都执行完,而之后添加进来的任务,需要等待任务A执行完毕才可以执行,从而达到将任务A隔离的目的,具体过程如下图所示: 
 如果将barrier任务之前和之后的并发任务换为读操作,barrier任务本身换为写操作,就可以将dispatch_barrier_async /  dispatch_barrier_sync当做读者写者锁来使用了,下面把文初的使用普通锁实现的cache代码,用dispatch_barrier_async重写,做下对比: //实现一个简单的cache(使用普通锁) - (void)setCache:(id)cacheObject forKey:(NSString *)key {     if (key.length == 0) {         return;     }     [_cacheLock lock];     self.cacheDic[key] = cacheObject;     ...     [_cacheLock unlock]; }  - (id)cacheForKey:(NSString *key) {     if (key.length == 0) {         return nil;     }     [_cacheLock lock];     id cacheObject = self.cacheDic[key];     ...     [_cacheLock unlock];     return cacheObject; } 
 //实现一个简单的cache(使用读者写者锁) static dispatch_queue_t queue = dispatch_queue_create("com.gfzq.testQueue", DISPATCH_QUEUE_CONCURRENT);  - (void)setCache:(id)cacheObject forKey:(NSString *)key {     if (key.length == 0) {         return;     }     dispatch_barrier_async(queue, ^{         self.cacheDic[key] = cacheObject;         ...     }); }  - (id)cacheForKey:(NSString *key) {     if (key.length == 0) {         return nil;     }     __block id cacheObject = nil;     dispatch_sync(queue, ^{         cacheObject = self.cacheDic[key];         ...     });     return cacheObject; } 
 这样实现的cache就可以并发执行读操作,同时又有效地隔离了写操作,兼顾了安全和效率。 (编辑:南平站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |