iOS的atomic并不能保证绝对的线程安全

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的代价小,可以考虑直接使用同步队列。
所以可以把上面异步栅拦分发队列换成同步的执行

你可能感兴趣的:(iOS的atomic并不能保证绝对的线程安全)