做一个网站的流程,重庆网站建设川娃子,宁波网站建设公司哪家口碑好,阜阳城乡建设局网站在 Objective - C 里#xff0c;atomic 特性并不能保证对象是完全线程安全的#xff0c;下面从其基本原理、部分线程安全场景以及局限性来详细说明#xff1a;
先看一个例子
#import Foundation/Foundation.hinterface MyClass : NSObject
property (atomic, assi…在 Objective - C 里atomic 特性并不能保证对象是完全线程安全的下面从其基本原理、部分线程安全场景以及局限性来详细说明
先看一个例子
#import Foundation/Foundation.hinterface MyClass : NSObject
property (atomic, assign) NSInteger count;
endimplementation MyClass- (void)incrementCount {self.count self.count 1;
}endint main(int argc, const char * argv[]) {autoreleasepool {MyClass *myObject [[MyClass alloc] init];dispatch_queue_t concurrentQueue dispatch_queue_create(com.example.concurrentQueue, DISPATCH_QUEUE_CONCURRENT);// 创建多个线程同时调用 incrementCount 方法for (int i 0; i 1000; i) {dispatch_async(concurrentQueue, ^{[myObject incrementCount];});}// 等待所有任务完成dispatch_barrier_sync(concurrentQueue, ^{NSLog(Final count: %ld, (long)myObject.count);});}return 0;
}
多次执行结果 Final count: 996 Final count: 995 Final count: 991 Final count: 1000 Final count: 987 也就是说结果是不确定大概率不符合预期≠1000那么很显然多线程多操下atomic并没有保证线程安全
咱们做如下修改其他代码不变
property (nonatomic, assign) NSInteger count;
多次执行结果 Final count: 561 Final count: 765 Final count: 567 Final count: 669 Final count: 720 比原来少了也就是说atomic确实带来了一定的安全效果只不过不完全保证 atomic 基本原理
atomic 是属性声明时的一个特性使用 atomic 修饰的属性在其生成的 setter 和 getter 方法里会加锁以此来保证同一时间只有一个线程能对该属性进行读写操作。例如下面的代码
interface MyClass : NSObject
property (atomic, strong) NSString *myString;
endimplementation MyClass
// 编译器自动生成的类似 setter 方法伪代码示意
- (void)setMyString:(NSString *)myString {synchronized(self) {_myString myString;}
}// 编译器自动生成的类似 getter 方法伪代码示意
- (NSString *)myString {synchronized(self) {return _myString;}
}
end
部分线程安全场景
在单纯的属性读写操作中atomic 能够在一定程度上保证线程安全。比如多个线程同时对 myString 属性进行读写操作由于 setter 和 getter 方法加了锁同一时间只会有一个线程执行读写操作避免了数据竞争的问题。
atomic 的局限性
复合操作不安全atomic 只能保证单个属性的 setter 和 getter 方法是线程安全的对于复合操作无法保证线程安全。例如下面的代码
interface MyClass : NSObject
property (atomic, assign) NSInteger count;
endimplementation MyClass- (void)incrementCount {// 这是一个复合操作先读再写self.count self.count 1;
}end
在 incrementCount 方法中先读取 count 的值然后加 1 再赋值回去。虽然 count 属性使用了 atomic 修饰但其 setter 和 getter 方法分别是线程安全的但整个 incrementCount 操作不是原子的。在多线程环境下可能会出现多个线程同时读取到相同的 count 值然后各自加 1 再赋值回去导致最终的 count 值不符合预期。 对象的其他操作不安全atomic 仅针对属性的 setter 和 getter 方法加锁对于对象的其他操作如调用对象的方法并不能保证线程安全。例如
interface MyClass : NSObject
property (atomic, strong) NSMutableArray *myArray;
endimplementation MyClass- (void)addObjectToArray:(id)object {// 这里对 myArray 进行操作不是 setter 和 getter 方法atomic 无法保证安全[self.myArray addObject:object];
}end
在 addObjectToArray 方法中虽然 myArray 属性使用了 atomic 修饰但对 myArray 调用 addObject: 方法时并没有加锁多个线程同时调用该方法可能会导致数据不一致的问题。
综上所述atomic 只是在属性的基本读写操作上提供了一定的线程安全保障但不能保证对象在多线程环境下的完全线程安全。如果需要更全面的线程安全还需要使用其他同步机制如 synchronized、NSLock 等来保护复合操作和对象的其他操作。
atomic vs. 真正的线程安全
atomicsynchronizedGCD 串行队列NSLock保证 setter/getter 线程安全✅✅✅✅保证多个线程同时操作的安全性❌✅✅✅推荐用于简单属性多个操作依赖同一数据并发任务处理多线程数据访问性能较好稍差高效中等