美文网首页
iOS刨根问底之atomic为什么不能保证线程安全

iOS刨根问底之atomic为什么不能保证线程安全

作者: Hpwu | 来源:发表于2020-04-02 19:30 被阅读0次

atomicobjc中是用来修饰属性,表示属性的写操作是一个原子操作。本文以几段代码为例,分析为什么atomic修饰的属性并不是线程安全的。

定义一个带有atomic属性的Model

@interface Model : NSObject
@property (atomic, assign) NSInteger index;
@end
@implementation Model
@end

首先我们看下述代码代码一。输出结果大家都知道是无序的。

dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);
Model *m = [Model new];
for (int i = 0; i < 100; i++) {
    dispatch_async(queue, ^{
        m.index++;
        NSLog(@"index = %ld", m.index);
    });
}

这段代码代码二,大家也知道结果,输出是有序的。

dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);
NSLock *lock = [NSLock new];
Model *m = [Model new];
for (int i = 0; i < 100; i++) {
    dispatch_async(queue, ^{
        [lock lock];
        m.index++;
        NSLog(@"index = %ld", m.index);
        [lock unlock];
    });
}

接下来,我们拆分一下有序的代码,代码三。ok,这部分也是有序的,没有问题。

dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);
NSLock *lock = [NSLock new];
Model *m = [Model new];

for (int i = 0; i < 100; i++) {
    dispatch_async(queue, ^{
        [lock lock];
        m.index++;
        [lock unlock];
        
        [lock lock];
        NSLog(@"index = %ld", m.index);
        [lock unlock];
    });
}

调整一下代码,代码四

dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);
NSLock *lock = [NSLock new];
Model *m = [Model new];
for (int i = 0; i < 100; i++) {
    dispatch_async(queue, ^{
        m.index++;
        
        [lock lock];
        NSLog(@"index = %ld", m.index);
        [lock unlock];
    });
}

这段代码可能就需要思考一下了。首先m.index++;是原子的,NSLog(@"index = %ld", m.index);也是原子的,那么应该能顺序输出。但实际运行代码后发现,还是无序的。

最后一个例子,代码五

dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);

NSLock *lock1 = [NSLock new];
NSLock *lock2 = [NSLock new];
Model *m = [Model new];

for (int i = 0; i < 100; i++) {
    dispatch_async(queue, ^{
        [lock1 lock];
        m.index++;
        [lock1 unlock];
        
        [lock2 lock];
        NSLog(@"index = %ld", m.index);
        [lock2 unlock];
    });
}

可能已经被绕晕了,如果单独拿出这段代码,大家很快就能回答出来,无序的。

看完这五个例子,大家应该已经有答案了。实际上atomic能保证属性的写操作是原子的,导致atomic不能保证线程安全的原因是问题的规模。问题规模的扩大,导致锁操作的范围需要扩展,而属性的原子操作对于扩大规模后问题的解决没有任何帮助,所以atomic并不能保证线程安全。

相关文章

网友评论

      本文标题:iOS刨根问底之atomic为什么不能保证线程安全

      本文链接:https://www.haomeiwen.com/subject/qelfphtx.html