Atomic和Nonatomic属性的区别

Atomic和Nonatomic属性的区别

技术背景

在Objective - C编程中,atomicnonatomic是用于修饰属性的特性。在多线程环境下,对属性的读写操作可能会出现数据不一致或程序崩溃等问题,atomicnonatomic属性的出现就是为了应对这些问题,不同的属性特性在保证数据完整性和性能方面有不同的表现。

实现步骤

1. 声明atomic属性

如果不指定nonatomic,属性默认就是atomic的。例如:

1
@property (retain) NSString *name;

2. 声明nonatomic属性

需要显式添加nonatomic关键字。例如:

1
@property (nonatomic, retain) NSString *name;

3. 合成属性的方法实现

在使用@synthesize合成属性的方法实现时,atomicnonatomic会生成不同的代码。

nonatomic属性生成的代码示例:

1
2
3
4
5
6
7
8
9
10
11
// @property(nonatomic, retain) UITextField *userName;
// 大致生成如下代码
- (UITextField *) userName {
return userName;
}

- (void) setUserName:(UITextField *)userName_ {
[userName_ retain];
[userName release];
userName = userName_;
}

atomic属性生成的代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// @property(retain) UITextField *userName;
// 大致生成如下代码
- (UITextField *) userName {
UITextField *retval = nil;
@synchronized(self) {
retval = [[userName retain] autorelease];
}
return retval;
}

- (void) setUserName:(UITextField *)userName_ {
@synchronized(self) {
[userName_ retain];
[userName release];
userName = userName_;
}
}

核心代码

下面是一个简单的示例,展示了atomicnonatomic属性的声明和使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#import <Foundation/Foundation.h>

@interface MyClass : NSObject

@property (atomic, retain) NSString *atomicName;
@property (nonatomic, retain) NSString *nonatomicName;

@end

@implementation MyClass

@synthesize atomicName;
@synthesize nonatomicName;

@end

int main(int argc, const char * argv[]) {
@autoreleasepool {
MyClass *obj = [[MyClass alloc] init];
obj.atomicName = @"Atomic Value";
obj.nonatomicName = @"Nonatomic Value";
NSLog(@"Atomic Name: %@", obj.atomicName);
NSLog(@"Nonatomic Name: %@", obj.nonatomicName);
[obj release];
}
return 0;
}

最佳实践

atomic属性的使用场景

当属性会在多线程环境下被访问时,使用atomic属性可以保证每次获取到的是一个完整的、未被破坏的值。例如,在多线程中对一个共享的计数器进行操作时,可以将计数器属性声明为atomic

1
2
3
4
5
@interface Counter : NSObject

@property (atomic, assign) NSInteger count;

@end

nonatomic属性的使用场景

如果属性不会被多个线程同时访问,或者对性能要求较高,可以使用nonatomic属性。例如,在单线程环境下使用的属性,或者频繁读写的属性。

1
2
3
4
5
@interface SingleThreadObject : NSObject

@property (nonatomic, retain) NSString *singleThreadName;

@end

常见问题

1. atomic属性是否就意味着线程安全?

atomic属性并不能完全保证线程安全。它只是保证了属性的读写操作是原子的,但在多个依赖属性的场景下,仍然可能出现数据不一致的问题。例如:

1
2
3
@property(atomic, copy) NSString *firstName;
@property(atomic, copy) NSString *lastName;
@property(readonly, atomic, copy) NSString *fullName;

当一个线程同时修改firstNamelastName,另一个线程在中间读取fullName时,可能会得到不一致的数据。解决这种问题需要使用事务模型或其他同步机制。

2. atomicnonatomic属性在性能上有多大差异?

在单线程环境下,atomic属性的性能开销相对较小,但在多线程竞争的情况下,atomic属性可能会比nonatomic属性慢很多。例如,在某些测试中,使用atomic属性的访问开销可能比nonatomic属性高出20倍甚至更多。所以在性能敏感的场景下,需要谨慎使用atomic属性。


Atomic和Nonatomic属性的区别
https://119291.xyz/posts/difference-between-atomic-and-nonatomic-attributes/
作者
ww
发布于
2025年5月26日
许可协议