atomic只能保证属性的存取是线程安全的,并不能保证整个对象是线程安全的。
首先看一下代码以及打印结果:
@property (atomic, assign) NSInteger intA; //有一个atomic的属性,表示是原子的
- (void)viewDidLoad {
[super viewDidLoad];
//开启一个线程对intA的值+1
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
for (int i = 0;i < 1000;i ++){
self.intA = self.intA + 1;
}
NSLog(@"intA : %ld",(long)self.intA);
});
//开启一个线程对intA的值+1
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
for (int i = 0;i < 1000;i ++){
self.intA = self.intA + 1;
}
NSLog(@"intA : %ld",(long)self.intA);
});
错误的分析是:因为intA是atomic修饰的,所以是线程安全的,在+1的时候,只会有一个线程去操作,所以最终的打印结果必定有一个是2000。
结果:
2018-09-12 08:47:20.019123+0800 Test[1019:48584] intA : 1186
2018-09-12 08:47:20.019123+0800 Test[1019:48583] intA : 896
只是对set方法加锁,而我们程序里面的self.intA = self.intA + 1; 这一部分不是线程安全的,后面这个+1操作不是线程安全的,所以要想最终得到2000的结果,需要使用锁对self.intA = self.intA + 1加锁,代码如下,这里可以将atomic修饰词改为nonatomic,最终修改的代码以及打印结果如下
@property (nonatomic, assign) NSInteger intA;
- (void)viewDidLoad {
[super viewDidLoad];
self.lock = [[NSLock alloc] init];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
for (int i = 0;i < 1000;i ++){
[self.lock lock];
self.intA = self.intA + 1;
[self.lock unlock];
}
NSLog(@"intA : %ld",(long)self.intA);
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
for (int i = 0;i < 1000;i ++){
[self.lock lock];
self.intA = self.intA + 1;
[self.lock unlock];
}
NSLog(@"intA : %ld",(long)self.intA);
});
}
打印结果
2018-09-12 09:06:57.071829+0800 Test[2200:97290] intA : 1360
2018-09-12 09:06:57.071966+0800 Test[2200:97293] intA : 2000