最近在一些简书或博客中看到一些使用GCD来保证操作NSMutableArray的多线程安全性,甚至在高质量一书中也提到了,代码如下:
// 创建一个并发队列
@interfacetestCurrentString :NSObject
- (NSString*)getSomeString;
- (void)setSomeString:(NSString*)xxx;
@end
@implementationtestCurrentString
{
dispatch_queue_t conCurrent;
NSString*someString;
}
- (instancetype)init {
self = [superinit];
if(self) {
conCurrent = dispatch_queue_create("testString", DISPATCH_QUEUE_CONCURRENT);
someString=@"1";
}
return self;
}
- (NSString*)getSomeString {
__blockNSString*localString;
dispatch_sync(conCurrent, ^{
localString =someString;
NSLog(@"current thread is %p", [NSThread currentThread]);
});
returnlocalString;
}
- (void)setSomeString:(NSString*)xxx {
dispatch_barrier_async(conCurrent, ^{
someString= xxx;
});
}
@end
testCurrentString *str = [[testCurrentString alloc] init];
for(int i =0; i <10; ++i) {
dispatch_async(conQueue, ^{
NSLog(@"在%@进行第%@个操作,线程:%p", [[NSDate date] description], str.getSomeString, [NSThread currentThread]);
});
}
疑惑:1. 如果是上文说的,getSomeString里用了dispatch_sync,那么不是真正的并发读取吗?因为我们知道sync永远只有在当前线程执行完才执行后续的操作,同时只在一个线程里执行
2. 如果改成dispatch_async,有什么问题?
说明:
再回答上面的问题前,说一个现象:
dispatch_queue_tserialQueue = dispatch_queue_create("serial.queue", DISPATCH_QUEUE_SERIAL);
dispatch_queue_tglobalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH,0);
dispatch_sync(globalQueue, ^{
BOOLres1 = [NSThreadisMainThread];
BOOLres2 = dispatch_get_specific("key") !=NULL;
NSLog(@"is main thread: %zd --- is main queue: %zd", res1, res2);})
这段代码res1执行输出是多少?true or false?
答案:输出是 true,为什么?不是应该执行globalQueue里的一个子线程吗?
不是的,苹果为了减少线程切换,而做了优化,只在当前线程执行,所以判断的话,就输出true了
好了,在理解了这个现象后,我在回答上面的问题,如果改成async,那么怎么返回值呢??
上面的sync和dispatch_barrier_async 只是保证读读不互斥,而读写互斥,所以外部在用async来读取的时候,就是并发读取
而写的时候,就能做到写的时候不让读,直到写完,做到了读写的多线程的安全