iOS中使用atomic就能保证安全了吗?
2021-08-19 本文已影响0人
希尔罗斯沃德_董
什么是atomic?
iOS 中属性修饰符有atomic 和 nonatomic ,atomic表示原子性,反之nonatomic是非原子性。所谓原子性,在这里就是保证属性的setter方法和getter方法操作的原子性。那么,是不是使用atomic就能保证线程安全了呢?
atomic修饰可变对象
没错,如果使用atomic修饰的是可变对象的话,是无法保证线程安全,就比如NSMutableArray,它可以insert、delete等操作,这些操作并不会通过setter方法,也就失去了atomic的保护范围。但是如果atomic修饰的是一普通对象就一定线程安全吗?
直接访问成员变量
要回答这个问题还得从setter和getter方说起,以setter方法为例假设这样一个属性 @property (atomic, strong) id object;他的setter方法(ARC下)应该是:
- (void)setObject:(id)object
{
_object = object;
}
在底层他要实现原子操作,肯定需要加一些类似锁或者同步之类的操作,假设它的原子操作模型如下:
- (void)setObject:(id)object
{
[lock lock];
_object = object;
[lock unlock];
}
这里在set方法进行赋值时进行加锁以保证线程安全。但是,如果我们并没有调用setter方法赋值,而是直接访问实例变量_object,它还是线程安全吗?就比如下面的代码:
- (void)test
{
dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
for (int i = 0; i < 100000; i++) {
dispatch_async(globalQueue, ^{
[self update];
NSLog(@"%@", @(i));
});
}
[self update];
}
- (void)update
{
_object = [[NSObject alloc] init];
}
这里的代码直接访问的是实例变量_object,并没有走set方法,显然是无法保证线程安全的。所以使用atomic是无法保证线程安全的,要保证线程安全显然还是要做更多细致的考虑。