提问人:Alex Wayne 提问时间:2/26/2009 最后编辑:Chirag KothiyaAlex Wayne 更新时间:5/3/2023 访问量:530778
原子属性和非原子属性之间有什么区别?
What's the difference between the atomic and nonatomic attributes?
问:
财产声明中的含义和含义是什么?atomic
nonatomic
@property(nonatomic, retain) UITextField *userName;
@property(atomic, retain) UITextField *userName;
@property(retain) UITextField *userName;
这三者之间的操作区别是什么?
答:
原子:
原子保证对属性的访问将以原子方式执行。例如,它总是返回一个完全初始化的对象,一个线程上任何属性的 get/set 都必须完成,然后另一个线程才能访问它。
如果你想象以下函数同时发生在两个线程上,你就会明白为什么结果会不漂亮。
-(void) setName:(NSString*)string
{
if (name)
{
[name release];
// what happens if the second thread jumps in now !?
// name may be deleted, but our 'name' variable is still set!
name = nil;
}
...
}
优点:每次返回完全初始化的对象使其成为多线程的最佳选择。
缺点:性能下降,使执行速度变慢
非原子 :
与 Atomic 不同,它不能确保每次都返回完全初始化的对象。
优点:极快的执行速度。
缺点:在多线程的情况下出现垃圾值的可能性。
评论
最简单的答案是:你的后两个例子之间没有区别。默认情况下,属性访问器是原子的。
非垃圾回收环境中的原子访问器(即使用 retain/release/autorelease 时)将使用锁来确保另一个线程不会干扰值的正确设置/获取。
请参阅 Apple 的 Objective-C 2.0 文档的“性能和线程”部分,了解更多信息以及创建多线程应用时的其他注意事项。
评论
这在 Apple 的文档中进行了解释,但以下是实际发生的一些示例。
请注意,没有“atomic”关键字,如果不指定“nonatomic”,则该属性为atomic,但显式指定“atomic”将导致错误。
如果未指定“nonatomic”,则该属性是 atomic,但如果需要,您仍然可以在最新版本中显式指定“atomic”。
//@property(nonatomic, retain) UITextField *userName;
//Generates roughly
- (UITextField *) userName {
return userName;
}
- (void) setUserName:(UITextField *)userName_ {
[userName_ retain];
[userName release];
userName = userName_;
}
现在,原子变体有点复杂:
//@property(retain) UITextField *userName;
//Generates roughly
- (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_;
}
}
基本上,原子版本必须采取锁来保证线程安全,并且还增加了对象上的引用计数(以及自动释放计数以平衡它),以便保证对象对调用者存在,否则如果另一个线程正在设置该值,则存在潜在的竞争条件, 导致 ref 计数降至 0。
实际上,这些东西的工作方式有很多不同的变体,具体取决于属性是标量值还是对象,以及保留、复制、只读、非原子等如何交互。一般来说,属性合成器只知道如何为所有组合做“正确的事情”。
评论
@property (assign) id delegate;
-Os
[self.delegate delegateMethod:self];
foo.delegate = nil; self.foo = nil; [super dealloc];
_val
val
copy
retain
-retain
最后两个是相同的;“atomic”是默认行为(请注意,它实际上不是一个关键字;它只是通过缺少 -- 在最新版本的 llvm/clang 中被添加为关键字)。非原子
来指定atomic
假设您@synthesizing方法实现,原子与非原子会更改生成的代码。如果你正在编写自己的 setter/getter,atomic/nonatomic/retain/assign/copy 只是建议。(注意:@synthesize现在是最新版本的 LLVM 中的默认行为。也不需要声明实例变量;它们也将自动合成,并在其名称前面加上一个以防止意外直接访问)。_
使用“原子”,合成的 setter/getter 将确保始终从 getter 返回或由 setter 设置整个值,而不管任何其他线程上的 setter 活动如何。也就是说,如果线程 A 位于 getter 的中间,而线程 B 调用 setter,则实际的可行值(很可能是自动释放的对象)将返回给 A 中的调用者。
在 中,不作任何此类保证。因此,比“原子”快得多。nonatomic
nonatomic
“原子”不做的是对线程安全做出任何保证。如果线程 A 同时调用 getter,线程 B 和 C 调用具有不同值的 setter,则线程 A 可能会返回三个值中的任何一个 -- 调用任何 setter 之前的值,或者传递给 B 和 C 中的 setter 的值中的任何一个。 没办法说。
确保数据完整性 - 多线程编程的主要挑战之一 - 可以通过其他方式实现。
除此之外:
atomicity
当多个依赖属性起作用时,单个属性也无法保证线程安全。
考虑:
@property(atomic, copy) NSString *firstName;
@property(atomic, copy) NSString *lastName;
@property(readonly, atomic, copy) NSString *fullName;
在这种情况下,线程 A 可以通过调用然后调用 来重命名对象。同时,线程 B 可能会在线程 A 的两次调用之间调用,并将接收新的名字和旧姓氏。setFirstName:
setLastName:
fullName
为了解决这个问题,你需要一个事务模型。即某种其他类型的同步和/或排除,允许在更新依赖属性时排除对的访问。fullName
评论
@property NSArray* astronomicalEvents;
atomic
retain/autorelease
atomic
没有这样的关键词“原子”
@property(atomic, retain) UITextField *userName;
我们可以使用上面的
@property(retain) UITextField *userName;
请参阅堆栈溢出问题,如果我使用 @property(atomic,retain)NSString *myString,我会遇到问题。
评论
了解差异的最佳方法是使用以下示例。
假设有一个名为“name”的原子字符串属性,如果你从线程 A 调用,从线程 B 调用,从线程 C 调用,那么不同线程上的所有操作都将串行执行,这意味着如果一个线程正在执行 setter 或 getter,那么其他线程将等待。[self setName:@"A"]
[self setName:@"B"]
[self name]
这使得属性“name”读/写安全,但如果另一个线程 D 同时调用,则此操作可能会产生崩溃,因为此处不涉及 setter/getter 调用。这意味着一个对象是读/写安全的 (ATOMIC),但不是线程安全的,因为另一个线程可以同时向该对象发送任何类型的消息。开发人员应确保此类对象的线程安全。[name release]
如果属性“name”是非原子的,那么上面示例中的所有线程 - A、B、C 和 D 将同时执行,产生任何不可预测的结果。在原子的情况下,A、B 或 C 中的任何一个将首先执行,但 D 仍然可以并行执行。
我在这里找到了一个关于原子和非原子性质的很好的解释。以下是一些来自同一内容的相关文本:
“原子”意味着它不能被分解。 在操作系统/编程术语中,原子函数调用是一个不能中断的函数 - 整个函数必须执行,并且在完成之前不会通过操作系统通常的上下文切换从 CPU 中交换出来。以防万一你不知道:由于 CPU 一次只能做一件事,操作系统会在很小的时间片内将对 CPU 的访问轮换到所有正在运行的进程,以给人一种多任务处理的错觉。CPU 调度程序可以(并且确实)在进程执行的任何时候中断进程 - 即使在函数调用中间也是如此。因此,对于像更新共享计数器变量这样的操作,其中两个进程可以尝试同时更新变量,它们必须以“原子方式”执行,即每个更新操作必须完整完成,然后才能将任何其他进程交换到 CPU 上。
所以我猜在这种情况下,原子意味着属性读取器方法不能中断 - 实际上意味着该方法读取的变量不能在中途更改其值,因为其他一些线程/调用/函数被交换到 CPU 上。
由于变量不能被中断,因此它们在任何时候包含的值(线程锁)都保证不会损坏,尽管确保此线程锁会使访问它们的速度变慢。 另一方面,变量不能提供这样的保证,但确实提供了更快访问的奢侈。总而言之,当你知道你的变量不会被多个线程同时访问时,就去加速。atomic
non-atomic
non-atomic
评论
原子
- 是默认行为
- 将确保在另一个进程访问变量之前,CPU 完成当前进程
- 速度不快,因为它确保了该过程完全完成
非原子
- 不是默认行为
- 更快(对于合成代码,即对于使用 @property 和 @synthesize 创建的变量)
- 不是线程安全的
- 当两个不同的进程同时访问同一变量时,可能会导致意外行为
语法和语义已经由这个问题的其他优秀答案很好地定义了。因为执行和性能不是很详细,所以我会补充我的答案。
这三者在功能上有什么区别?
我一直认为原子是默认的,这很奇怪。在我们工作的抽象级别上,使用类的原子属性作为载体来实现 100% 的线程安全是一个极端情况。对于真正正确的多线程程序,程序员的干预几乎肯定是必需的。同时,性能特征和执行尚未深入详细说明。这些年来,我编写了一些高度多线程的程序,我一直在声明我的属性,因为原子对于任何目的都是不明智的。在讨论原子和非原子性质的细节这个问题时,我做了一些分析,遇到了一些奇怪的结果。nonatomic
执行
还行。我想澄清的第一件事是,锁定实现是实现定义和抽象的。路易斯在他的例子中引用了 -- 我把这看作是造成混淆的常见根源。实现实际上并不使用 ;它使用对象级旋转锁。Louis 的插图非常适合使用我们都熟悉的结构的高级插图,但重要的是要知道它不使用 .@synchronized(self)
@synchronized(self)
@synchronized(self)
另一个区别是原子属性将在 getter 中保留/释放对象循环。
性能
有趣的是:在某些情况下,在无争议(例如单线程)的情况下,使用原子属性访问的性能可能非常快。在不太理想的情况下,使用原子访问的成本可能是 的 20 倍以上。而使用 7 个线程的有争议的案例对于三字节结构(2.2 GHz Core i7 Quad Core,x86_64)慢 44 倍。三字节结构是一个非常慢的属性的示例。nonatomic
有趣的旁注:三字节结构的用户定义访问器比合成的原子访问器快 52 倍;或合成非原子接入器速度的 84%。
有争议的案件中的对象也可以超过 50 次。
由于优化的数量和实现的变化,在这些情况下衡量现实世界的影响是相当困难的。您可能经常听到类似“相信它,除非您分析并发现它是一个问题”。由于抽象级别,实际上很难衡量实际影响。从配置文件中收集实际成本可能非常耗时,并且由于抽象,非常不准确。同样,ARC 与 MRC 可以产生很大的不同。
因此,让我们退后一步,不关注属性访问的实现,我们将包括常见的可疑因素,例如 ,并检查一些真实世界的高级结果,这些结果在无争议的情况下对 getter 进行了多次调用(以秒为单位的值):objc_msgSend
NSString
- 湄公河委员会 |非原子 |手动实现的 getter:2
- 湄公河委员会 |非原子 |合成吸气剂:7
- 湄公河委员会 |原子 |合成吸气剂:47
- 电弧 |非原子 |合成的 getter:38(注意:ARC 在此处添加 ref count 循环)
- 电弧 |原子 |合成吸气剂:47
正如您可能已经猜到的那样,参考计数活动/循环是原子和 ARC 下的重要贡献者。在有争议的案件中,您还会看到更大的差异。
虽然我非常关注性能,但我仍然说语义第一!同时,对于许多项目来说,性能的优先级较低。但是,了解您使用的技术的执行细节和成本肯定不会有什么坏处。您应该根据自己的需求、目的和能力使用正确的技术。希望这将为您节省几个小时的比较时间,并帮助您在设计程序时做出更明智的决定。
评论
NSString
-ARC atomic (BASELINE): 100% -ARC nonatomic, synthesised: 94% -ARC nonatomic, user defined: 86% -MRC nonatomic, user defined: 5% -MRC nonatomic, synthesised: 19% -MRC atomic: 102%
@synchronized
@synchronized
@synchronized
原子意味着只有一个线程访问变量(静态类型)。Atomic是线程安全的,但它很慢。
非原子意味着多个线程访问变量(动态类型)。非原子是线程不安全的,但它速度很快。
在阅读了这么多文章、Stack Overflow 帖子并制作了演示应用程序来检查变量属性属性之后,我决定将所有属性信息放在一起:
atomic
违约nonatomic
strong = retain
违约weak = unsafe_unretained
retain
assign
违约unsafe_unretained
copy
readonly
readwrite
违约
在 iOS 中的变量属性属性或修饰符一文中,您可以找到上述所有属性,这肯定会对您有所帮助。
atomic
atomic
表示只有一个线程访问变量(静态类型)。atomic
是线程安全的。- 但它的性能很慢
atomic
是默认行为- 非垃圾回收环境中的原子访问器(即使用 retain/release/autorelease 时)将使用锁来确保另一个线程不会干扰值的正确设置/获取。
- 它实际上不是一个关键字。
例:
@property (retain) NSString *name; @synthesize name;
nonatomic
nonatomic
表示多线程访问变量(动态类型)。nonatomic
线程不安全。- 但它的性能很快
nonatomic
不是默认行为。我们需要在 property 属性中添加关键字。nonatomic
- 当两个不同的进程(线程)同时访问同一变量时,可能会导致意外行为。
例:
@property (nonatomic, retain) NSString *name; @synthesize name;
评论
原子 = 线程安全
非原子 = 无线程安全
螺纹安全:
如果实例变量在从多个线程访问时行为正确,则实例变量是线程安全的,而不管运行时环境如何调度或交错执行这些线程,并且调用代码没有额外的同步或其他协调。
在我们的语境中:
如果线程更改了实例的值,则更改后的值可供所有线程使用,并且一次只能有一个线程更改该值。
使用地点 :atomic
如果要在多线程环境中访问实例变量。
含义:atomic
没有那么快,因为不需要从运行时进行任何看门狗工作。nonatomic
nonatomic
使用地点 :nonatomic
如果实例变量不会被多个线程更改,则可以使用它。它提高了性能。
评论
默认值为 ,这意味着每当使用该属性时,它确实会降低性能,但它是线程安全的。Objective-C 所做的是设置一个锁,因此只要执行 setter/getter 就只有实际的线程才能访问该变量。atomic
具有 ivar _internal的属性的 MRC 示例:
[_internal lock]; //lock
id result = [[value retain] autorelease];
[_internal unlock];
return result;
所以最后两个是一样的:
@property(atomic, retain) UITextField *userName;
@property(retain) UITextField *userName; // defaults to atomic
另一方面,不会向代码添加任何内容。因此,只有您自己编写安全机制代码时,它才是线程安全的。nonatomic
@property(nonatomic, retain) UITextField *userName;
关键字根本不需要编写为第一个属性属性。
别忘了,这并不意味着整个属性是线程安全的。只有 setter/getter 的方法调用是。但是,如果您使用 setter,然后同时使用 2 个不同线程的 getter,它也可能被破坏!
如果您在多线程代码中使用您的属性,那么您将能够看到非原子属性和原子属性之间的区别。非原子比原子快,原子是线程安全的,而不是非原子的。
Vijayendra Tripathi 已经给出了一个多线程环境的例子。
Atomic是线程安全的,它很慢,并且它很好地保证(不保证)无论有多少线程尝试在同一区域上访问,都只提供锁定的值。使用 atomic 时,在此函数中编写的一段代码将成为临界部分的一部分,一次只能执行一个线程。
它只保证了螺纹的安全;它不保证这一点。我的意思是你为你的车聘请了一位专业的司机,但这并不能保证汽车不会发生事故。但是,概率仍然是最小的。
原子 - 它不能被分解,所以结果是意料之中的。使用非原子 - 当另一个线程访问内存区域时,它可以修改它,因此结果是出乎意料的。
代码讨论:
原子使属性线程的 getter 和 setter 安全。例如,如果你写了:
self.myProperty = value;
是线程安全的。
[myArray addObject:@"Abc"]
不是线程安全的。
评论
原子属性确保保留一个完全初始化的值,无论有多少线程在它上面做 getter 和 setter。
nonatomic 属性指定合成的访问器只是直接设置或返回一个值,不能保证从不同的线程同时访问相同的值时会发生什么。
原子意味着一次只有一个线程可以访问变量(静态类型)。Atomic是线程安全的,但它很慢。
非原子意味着多个线程可以同时访问变量(动态类型)。非原子是线程不安全的,但它速度很快。
如果您使用的是原子,则意味着线程将是安全和只读的。如果你使用的是非原子的,则意味着多个线程访问变量并且是线程不安全的,但它执行速度很快,完成了读写操作;这是一种动态类型。
开始之前:您必须知道内存中的每个对象都需要从内存中释放,才能产生新的写入器。你不能像在纸上那样简单地在某件事上写字。您必须首先擦除(取消)它,然后才能写入它。如果在擦除完成(或完成一半)并且尚未写入任何内容(或写入一半)并且您尝试阅读它的那一刻可能会非常有问题!原子和非原子可帮助您以不同的方式处理此问题。
原子
将永远保证
- 如果两个不同的人想同时阅读和写作,你的论文不会被烧毁!--> 即使在竞争条件下,您的应用程序也永远不会崩溃。
- 如果一个人试图写,并且只写了 8 个字母中的 4 个,那么中间就不能读,只有当所有 8 个字母都写完时才能完成阅读 --> 在“仍在写入的线程”上不会发生读取(get),即如果有 8 个字节到字节要写入, 并且只写入了 4 个字节——直到那一刻,您都不允许从中读取。但是既然我说它不会崩溃,那么它将从自动释放对象的值中读取。
- 如果在写作之前,你已经删除了以前写在纸上的内容,然后有人想阅读,你仍然可以阅读。如何?您将从类似于 Mac OS 垃圾箱的内容中读取(因为垃圾箱尚未 100% 删除......它处于不确定状态) ---> 如果 ThreadA 要读取,而 ThreadB 已经释放写入,您将从 ThreadB 的最终完全写入值中获取一个值,或者从自动释放池中获取一些值。
保留计数是在 Objective-C 中管理内存的方式。 创建对象时,该对象的保留计数为 1。当您发送时 对象是 Retain 消息,其保留计数递增 1。什么时候 向对象发送释放消息时,其保留计数会递减 作者 1.当您向对象发送自动释放消息时,其保留计数 在将来的某个阶段递减 1。如果对象保留 计数减少到 0,则解除分配。
- Atomic 不能保证线程安全,尽管它对于实现线程安全很有用。线程安全与你如何编写代码/你从哪个线程队列读取/写入有关。它只保证不可崩溃的多线程。
什么?!多线程和线程安全不同吗?
是的。多线程意味着:多个线程可以同时读取一段共享数据,我们不会崩溃,但这并不能保证您不会从非自动释放的值中读取数据。通过线程安全,可以保证您阅读的内容不会自动释放。 我们之所以不默认将所有东西都原子化,是因为存在性能成本,而且对于大多数事情来说,实际上并不需要线程安全。我们代码的几个部分需要它,对于这几个部分,我们需要使用锁、互斥锁或同步以线程安全的方式编写代码。
nonatomic
- 由于没有像 Mac OS 垃圾箱这样的东西,所以没有人关心你是否总是得到一个值(<——这可能会导致崩溃),也没有人在乎是否有人试图在你的写作中读到一半(尽管在内存中写一半与在纸上写一半有很大不同,在记忆中它可能会给你一个疯狂的愚蠢值, 而在纸上你只能看到所写内容的一半) --> 不保证不会崩溃,因为它不使用自动释放机制。
- 不保证可以读取完整的书面值!
- 比原子快
总体而言,它们在两个方面有所不同:
崩溃与否,因为有或没有自动释放池。
允许在“尚未完成写入或空值”的中间读取,或者不允许并且仅在值完全写入时才允许读取。
原子:通过使用 NSLOCK 锁定线程来确保线程安全。
非原子:由于没有螺纹锁定机制,因此无法确保螺纹安全。
原子(默认)
Atomic 是默认值:如果您不键入任何内容,则您的属性是 原子。原子属性是可以保证的,如果你尝试从 它,您将返回一个有效值。它不作任何保证 关于该值可能是什么,但您将获得良好的数据,而不是 只是垃圾记忆。这允许您做的是,如果您有多个 线程或多个进程指向单个变量,一个 线程可以读取,另一个线程可以写入。如果他们同时击中 时间,则保证读取器线程获取以下两个值之一: 在更改之前或更改之后。原子不行 给你的是关于你这些价值观中的任何一种保证 可能会得到。原子确实经常与线程安全混淆, 这是不正确的。您需要保证您的线安全 其他方式。但是,原子将保证,如果您尝试阅读, 你得到了某种价值。
非原子
另一方面,非原子,正如你可能猜到的那样,只是意味着, “不要做那些原子化的东西。”你失去的是那个保证你 总能拿回一些东西。如果你试图在中间阅读 write,你可以取回垃圾数据。但是,另一方面,你去 快一点。因为原子属性必须做一些神奇的事情 为了保证您将获得一个值,它们会慢一些。如果 这是您经常访问的属性,您可能想放弃 精确到非原子,以确保您不会产生这种速度 罚款。
在此处查看更多信息:https://realm.io/news/tmi-objective-c-property-attributes/
为了简化整个混淆,让我们了解互斥锁。
互斥锁,顾名思义,锁定对象的可变性。因此,如果对象被一个类访问,则没有其他类可以访问同一对象。
在 iOS 中,还提供了互斥锁。现在,它以 FIFO 模式提供服务,并确保流不受共享同一实例的两个类的影响。但是,如果任务位于主线程上,请避免使用原子属性访问对象,因为它可能会占用您的 UI 并降低性能。@sychronise
评论
事实是,他们使用自旋锁来实现原子属性。代码如下:
static inline void reallySetProperty(id self, SEL _cmd, id newValue,
ptrdiff_t offset, bool atomic, bool copy, bool mutableCopy)
{
id oldValue;
id *slot = (id*) ((char*)self + offset);
if (copy) {
newValue = [newValue copyWithZone:NULL];
} else if (mutableCopy) {
newValue = [newValue mutableCopyWithZone:NULL];
} else {
if (*slot == newValue) return;
newValue = objc_retain(newValue);
}
if (!atomic) {
oldValue = *slot;
*slot = newValue;
} else {
spin_lock_t *slotlock = &PropertyLocks[GOODHASH(slot)];
_spin_lock(slotlock);
oldValue = *slot;
*slot = newValue;
_spin_unlock(slotlock);
}
objc_release(oldValue);
}
- -Atomic 表示只有一个线程访问变量(静态类型)。
- -Atomic是线程安全的。
- -但它的性能很慢
如何声明:
由于原子是默认的,
@property (retain) NSString *name;
AND 在实现文件中
self.name = @"sourov";
假设与三个属性相关的任务是
@property (retain) NSString *name;
@property (retain) NSString *A;
@property (retain) NSString *B;
self.name = @"sourov";
所有属性并行工作(如异步工作)。
如果从线程 A 调用“name”,
和
同时,如果您调用
[self setName:@"Datta"]
从线程 B 开始,
现在,如果 *name 属性是非原子的,那么
- 它将返回 A 的值“Datta”
- 它将返回 B 的值“Datta”
这就是为什么非原子被称为线程不安全的原因,但由于并行执行,它的性能很快
现在,如果 *name 属性是原子的
- 它将确保 A 的值“Sourov”
- 然后它将返回 B 的值“Datta”
这就是为什么原子被称为线程安全,这就是为什么它被称为读写安全
这种情况操作将串行执行。而且性能慢
- 非原子意味着多线程访问变量(动态类型)。
- 非原子是线程不安全的。
- 但它的性能很快
-Nonatomic 不是默认行为,我们需要在 property 属性中添加 nonatomic 关键字。
对于 In Swift 确认 Swift 属性在 ObjC 意义上是非原子的。其中一个原因是你要考虑每个属性的原子性是否足以满足你的需求。
参考: https://forums.developer.apple.com/thread/25642
欲了解更多信息,请访问网站 http://rdcworld-iphone.blogspot.in/2012/12/variable-property-attributes-or.html
评论
atomic
原子属性 :- 当一个变量被分配了原子属性时,这意味着它只有一个线程访问,并且它将是线程安全的,并且在性能方面会很慢,将具有默认行为。
非原子属性 :- 当一个变量被分配了非原子属性时,这意味着它具有多线程访问,并且它不是线程安全的,并且在性能方面会很快,将具有默认行为,当两个不同的线程想要同时访问变量时,它会产生意想不到的结果。
评论
int
原子数 原子(默认)
Atomic 是默认值:如果您不键入任何内容,则您的属性是 原子。原子属性是可以保证的,如果你尝试从 它,您将返回一个有效值。它不作任何保证 关于该值可能是什么,但您将获得良好的数据,而不是 只是垃圾记忆。这允许您做的是,如果您有多个 线程或多个进程指向单个变量,一个 线程可以读取,另一个线程可以写入。如果他们同时击中 时间,则保证读取器线程获取以下两个值之一: 在更改之前或更改之后。原子不行 给你的是关于你这些价值观中的任何一种保证 可能会得到。原子确实经常与线程安全混淆, 这是不正确的。您需要保证您的线安全 其他方式。但是,原子将保证,如果您尝试阅读, 你得到了某种价值。
非原子
另一方面,非原子,正如你可能猜到的那样,只是意味着, “不要做那些原子化的东西。”你失去的是那个保证你 总能拿回一些东西。如果你试图在中间阅读 write,你可以取回垃圾数据。但是,另一方面,你去 快一点。因为原子属性必须做一些神奇的事情 为了保证您将获得一个值,它们会慢一些。如果 这是您经常访问的属性,您可能想放弃 精确到非原子,以确保您不会产生这种速度 罚款。访问
图片由 https://academy.realm.io/posts/tmi-objective-c-property-attributes/
原子性属性属性(原子和非原子)不会反映在相应的 Swift 属性声明中,但是当从 Swift 访问导入的属性时,Objective-C 实现的原子性保证仍然成立。
所以,如果你在 Objective-C 中定义了一个原子属性,当 Swift 使用它时,它将保持原子状态。
礼貌 https://medium.com/@YogevSitton/atomic-vs-non-atomic-properties-crash-course-d11c23f4366c
在一行中:
Atomic
是线程安全的。 线程不安全。Nonatomic
评论
Atomic
并不一定保证螺纹安全。考虑向 .虽然访问数组属性是线程安全的,但修改它根本不是线程安全的。@property(atomic) NSArray *names
在 Objective-C 中,原子属性的实现允许从不同的线程安全地读取和写入属性。对于非原子属性,当同时写入新值时,可以释放读取值的基础指针。
原子意味着只有一个线程访问变量(静态类型)。Atomic是线程安全的,但它很慢。非原子意味着多个线程访问变量(动态类型)。非原子是线程不安全的,但它速度很快。
评论