Definition 1.

Read-write lock actually is a special kind of spin lock, a read-write lock At the same time only one writer or more readers, but can’t there are both the reader and writer, if read/write locks Currently no reader, no writer, the writer can immediately get the read-write lock, otherwise it must spin, there until there is no any writer or reader. If the read-write lock has no writer, the reader can immediately acquire the read-write lock (pthread_rwlock).

  • Only one thread can write data at a time

  • Multiple threads are allowed to read at the same time

  • Both write and read operations are not allowed at the same time

2. Implementation scheme

There are roughly two implementations of read/write lock in iOS:

2.1 Read/write lock: pthread_rwlock

// Initialize lock pthread_rwlock_t lock; Pthread_rwlock_ init(&lock, NULL); Pthread_rwlock_rdlock (&lock); Pthread_rwlock_tryrdlock (&lock); // write a lock pthread_rwlock_wrlock (&lock); // write an attempt to lock pthread_rwlock_trywrLock (&lock); // Unlock pthread_rwlock__unlock (&lock); // destroy pthread_rwlock_destroy (&lock)Copy the code

2.2 dispatch_barrier_async

2.2.1 Implement read/write lock with Dispatch_barrier_Async

The queue passed in by this function must be created by dispatch_queue_cretate itself. Global queues cannot be created. The fence function cannot be used in global concurrent queues.

#import "ViewController.h" @interface ViewController () @property (nonatomic, copy) NSString *text; @property (nonatomic, strong) dispatch_queue_t concurrentQueue; @end @implementation ViewController @synthesize text = _text; - (void)viewDidLoad { [super viewDidLoad]; [self readWriteLock]; } - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { [self readWriteLock]; } - (void)readWriteLock { self.concurrentQueue = dispatch_queue_create("aaa", DISPATCH_QUEUE_CONCURRENT); For (int I = 0; i<10; I ++) {dispatch_async(dispatch_get_global_queue(0, 0), ^{self.text = [NSString stringWithFormat:@" %d", I]; }); } for (int i = 0; i<50; I++) {dispatch_async(dispatch_get_global_queue(0, 0), ^{NSLog(@" read %@ %@",[self text],[NSThread currentThread]); }); } for (int i = 10; i<20; I ++) {dispatch_async(dispatch_get_global_queue(0, 0), ^{self.text = [NSString stringWithFormat:@" %d", I]; }); }} - (void)setText:(NSString *)text {__weak typeof(self) weakSelf = self;  dispatch_barrier_sync(self.concurrentQueue, ^{ __strong typeof(weakSelf) strongSelf = weakSelf; strongSelf->_text = text; NSLog(@" write operation %@ %@",text,[NSThread currentThread]); Sleep (1); sleep(1); }); - (NSString *)text {__block NSString * t = nil; __weak typeof(self) weakSelf = self; dispatch_sync(self.concurrentQueue, ^{ __strong typeof(weakSelf) strongSelf = weakSelf; t = strongSelf->_text; Sleep (1); sleep(1); }); return t; } @endCopy the code
2.2.2 Implementation of read/write lock in AFN

In the AFN requestHeaderModificationQueue is a founded by AFHTTPRequestSerializer concurrent queue, use the concurrent queue to a NSMutableDictionary achieved much read a single write locks.

/ / concurrent queue self. RequestHeaderModificationQueue = dispatch_queue_create (" requestHeaderModificationQueue ", DISPATCH_QUEUE_CONCURRENT); - (NSDictionary *)HTTPRequestHeaders {NSDictionary__ block *value; Dispatch_sync (self requestHeaderModificationQueue, ^ {value = [NSDictionary dictionaryWithDictionary: self mutableHTTPRequestHeaders]; }); The return value. } // async method, Using dispatch_barrier_async/dispatch_barrier_sync ensures that there is only one thread at a time - (void)setValue:(NSString *)value ForHTTPHeaderField: (nsstrings *) field dispatch_barrier_async (self) requestHeaderModificationQueue,  ^{ [self . mutableHTTPRequestHeaders setValue:value forKey:field]; }); - (NSString *)valueForHTTPHeaderField:(NSString *)field {NSString __block *value; Dispatch_sync (self) requestHeaderModificationQueue, ^ {value = [self. MutableHTTPRequestHeaders valueForKey: field]. }); The return value. }Copy the code