1、iOS的atomic修饰的属性的读写的单个操作确实原子性的,但是它却不是线程安全的。
假设这个场景,有一个线程多次访问这个属性,在这个线程访问的期间这个属性是有可能被其他线程修改值的,所以atomic不能保证线程安全。
2、如何保证对读写的线程安全?
2.1 GCD 的栅拦分发队列 dispatch_barrier_async/dispatch_barrier_async
栅拦分发只对并发队列有效,栅拦分发必须单独执行,也就是说,如果执行到栅拦分发队列,那么一定是需要等执行在栅拦块之前的所有分发队列实行完成,栅拦分发队列才会执行,如下图示意。需要等所有读取操作完成(浅蓝色),才会执行写入操作,这样就保证读取同步。
读操作并发执行,但是读和写操作串行
2.2 读操作并发执行,但是读和写操作串行的示例代码
同步和异步分发能够达到同步效果
dispatch_queue_global_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) // dispatch_get_global_queue是一个并行队列
-(NSString*) someString{
__block NSString *newValue ;
dispatch_sync(queue, ^{ // 同步队列
newValue = someString;
})
return newValue;
}
-(void) setSomeString:(NSString *) someString{
dispatch_barrier_async(queue, ^{ // 栅拦队列
_someString = someString;
})
}
3、同步队列块和异步队列块的执行时间
我们需要知道,异步队列比同步队列在底层执行的时候回多一个步骤,异步会把要执行的块copy到堆的过程(因为这个块延迟执行,如果在栈上就有可能会被系统回收),同步的块直接分在栈上,直接同步执行。
所以异步分发队列的执行时间开销会比同步的开销大,如果异步分发队列执行的块逻辑要比copy的代价小,可以考虑直接使用同步队列。
所以可以把上面异步栅拦分发队列换成同步的执行
网友评论