iOS开发

NSMutableArray的安全性

2018-09-14  本文已影响53人  roger_Hunter

        最近在一些简书或博客中看到一些使用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来读取的时候,就是并发读取

而写的时候,就能做到写的时候不让读,直到写完,做到了读写的多线程的安全

上一篇下一篇

猜你喜欢

热点阅读