iOS基础:atomic和nonatomic区别

在创建属性时,总是习惯的创建nonatomic类型属性,也不管为什么这么用。其实在以往准备面试的时候,也只是理解个大概,再背诵一下,并没有真正的理解atomicnonatomic的区别,今天在和前辈讨论属性修饰的时候,突然开悟,立马写博客记录下来。

区别

先把他们的区别陈述一下:

  • atomic :系统生成的 getter/setter 会保证 get、set 操作的完整性,不受其他线程影响。但是atomic的速度慢。
  • nonatomic :无法保证get、set 操作的完整性。速度比atomic快很多。

很难懂,没关系。

使用atomic一定是线程安全的吗?

不是的,只能保证 get、set 操作的完整性,但不能保证线程的安全。

还是不懂,看举例。

举例

代码

1
2
3
@interface ELTestModel : NSObject
@property (atomic, copy) NSString *name;
@end
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
ELTestModel *model = [[ELTestModel alloc] init];

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
for (int i = 0; i < 999; i++) {
NSLog(@"1--");
model.name = @"11111111";
}
});

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
for (int i = 0; i < 999; i++) {
NSLog(@"2--");
model.name = @"22222222";
}
});

for (int i = 0; i < 9999; i++) {
NSLog(@"%@", model.name);
}

分析

如果这个atomic能保证线程安全,那么打印结果应该是先全为11111111,直到执行第二个for循环后,才会打印22222222
但是实际情况是:随机打印。

OK,现在一个问题已经说明,那么系统生成的 getter/setter 会保证 get、set 操作的完整性怎么理解呢。
其实是这样的,如果是atomic 修饰的对象,在setter或者getter方法内部,会开启一个锁,来防止赋值或者取值时出现问题。这也就是系统生成的 getter/setter 会保证 get、set 操作的完整性的意思。
像这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
- (void)setName:(NSString *)name
{
@synchronized(self) {
if (_name != name) {
[_name release];
_name = [name copy];
}
}
}

- (NSString *)name
{
@synchronized(self) {
return _name;
}
}

引伸

仍然是上述代码,怎么才能做到线程安全呢。其实很简单,在线程内部加锁。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@synchronized(self) {
for (int i = 0; i < 999; i++) {
NSLog(@"1--");
model.name = @"11111111";
}
}
});

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@synchronized(self) {
for (int i = 0; i < 999; i++) {
NSLog(@"2--");
model.name = @"22222222";
}
}
});

for (int i = 0; i < 9999; i++) {
NSLog(@"%@", model.name);
}

最后

atomic不能保证线程安全,只能保证set/get的时候安全,就相当于是在set/get时候,在代码上下加了锁,而不是在线程的开头和结尾加了锁。

请我吃一块黄金鸡块