atomic原子性,是property的关键字之一,会对属性的get,set操作加锁,保证读写的安全
例子🌰:
@interface ViewController ()
@property (nonatomic, copy)NSString *testAtomicStr;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
dispatch_queue_t queueGlobal = dispatch_get_global_queue(0, DISPATCH_QUEUE_PRIORITY_DEFAULT);
for (int i = 0; i < 1000; i ++) {
dispatch_async(queueGlobal, ^{
self.testAtomicStr = [NSString stringWithFormat:@"testAtomicStr%d",i];
NSLog(@"atomic test in asyn: %@",self.testAtomicStr);
});
}
}
上面代码运行会crash:Thread 9: EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
原因:
set操作会先release旧值再赋值新值,在多线程下,release的值可能被其他线程读取,造成空指针错误
修复:
把nonatomic改为atomic就行,atomic可以理解为在set,get操作时候加锁,效果类似下面代码,但不完全一样,因为atomic的锁只针对set,get操作
dispatch_queue_t queueGlobal = dispatch_get_global_queue(0, DISPATCH_QUEUE_PRIORITY_DEFAULT);
for (int i = 0; i < 1000; i ++) {
dispatch_async(queueGlobal, ^{
@synchronized (self) {
self.testAtomicStr = [NSString stringWithFormat:@"testAtomicStr%d",i];
NSLog(@"atomic test in asyn: %@",self.testAtomicStr);
}
});
}
那atomic就是安全的吗?
答案是否定的
例子🌰
@interface ViewController ()
@property (atomic, copy)NSString *testAtomicStr;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
dispatch_queue_t queueGlobal = dispatch_get_global_queue(0, DISPATCH_QUEUE_PRIORITY_DEFAULT);
for (int i = 0; i < 1000; i ++) {
dispatch_async(queueGlobal, ^{
self.testAtomicStr = [NSString stringWithFormat:@"testAtomicStr%d",i];
NSLog(@"atomic test in asyn: %@",self.testAtomicStr);
});
}
}
上面代码我们预期结果应该是下标0-999按顺序输出,实际结果是不符合预期的👇👇👇
2023-08-15 10:48:51.326968+0800 CTMVVMDemo1113[17653:2381770] atomic test in asyn: testAtomicStr1
2023-08-15 10:48:51.326968+0800 CTMVVMDemo1113[17653:2381764] atomic test in asyn: testAtomicStr1
2023-08-15 10:48:51.326975+0800 CTMVVMDemo1113[17653:2381766] atomic test in asyn: testAtomicStr3
2023-08-15 10:48:51.326968+0800 CTMVVMDemo1113[17653:2381769] atomic test in asyn: testAtomicStr2
2023-08-15 10:48:51.326991+0800 CTMVVMDemo1113[17653:2381768] atomic test in asyn: testAtomicStr4
2023-08-15 10:48:51.327031+0800 CTMVVMDemo1113[17653:2381765] atomic test in asyn: testAtomicStr5
2023-08-15 10:48:51.327089+0800 CTMVVMDemo1113[17653:2381773] atomic test in asyn: testAtomicStr6
2023-08-15 10:48:51.327140+0800 CTMVVMDemo1113[17653:2381770] atomic test in asyn: testAtomicStr8
2023-08-15 10:48:51.327163+0800 CTMVVMDemo1113[17653:2381774] atomic test in asyn: testAtomicStr7
2023-08-15 10:48:51.327169+0800 CTMVVMDemo1113[17653:2381775] atomic test in asyn: testAtomicStr9
2023-08-15 10:48:51.327175+0800 CTMVVMDemo1113[17653:2381764] atomic test in asyn: testAtomicStr10
结论atomic不完全安全,我们要结合具体场景合理使用