原子属性和非原子属性有什么区别?

发布于 2024-07-13 19:19:19 字数 257 浏览 4 评论 0原文

属性声明中的atomicnonatomic 是什么意思?

@property(nonatomic, retain) UITextField *userName;
@property(atomic, retain) UITextField *userName;
@property(retain) UITextField *userName;

这三者在操作上有什么区别呢?

What do atomic and nonatomic mean in property declarations?

@property(nonatomic, retain) UITextField *userName;
@property(atomic, retain) UITextField *userName;
@property(retain) UITextField *userName;

What is the operational difference between these three?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(28

空城旧梦 2024-07-20 19:19:20

原子 = 线程安全

非原子 = 无线程安全

线程安全:

如果从多个线程访问实例变量时行为正确,则实例变量是线程安全的,无论调度或交错如何运行时环境执行这些线程的过程,并且调用代码部分没有额外的同步或其他协调。

在我们的上下文中:

如果一个线程更改了实例的值,则更改后的值可供所有线程使用,并且一次只有一个线程可以更改该值。

在哪里使用原子:

如果要在多线程环境中访问实例变量。

atomic 的含义:

不如 nonatomic 快,因为 nonatomic 不需要运行时对其进行任何看门狗工作。

在哪里使用非原子:

如果实例变量不会被多个线程更改,则可以使用它。 它提高了性能。

Atomic = thread safety

Non-atomic = No thread safety

Thread safety:

Instance variables are thread-safe if they behave correctly when accessed from multiple threads, regardless of the scheduling or interleaving of the execution of those threads by the runtime environment, and with no additional synchronization or other coordination on the part of the calling code.

In our context:

If a thread changes the value of the instance the changed value is available to all the threads, and only one thread can change the value at a time.

Where to use atomic:

if the instance variable is gonna be accessed in a multithreaded environment.

Implication of atomic:

Not as fast as nonatomic because nonatomic doesn't require any watchdog work on that from runtime .

Where to use nonatomic:

If the instance variable is not gonna be changed by multiple threads you can use it. It improves the performance.

荆棘i 2024-07-20 19:19:20

阅读了这么多文章、Stack Overflow 帖子并制作了演示应用程序来检查可变属性属性后,我决定将所有属性信息放在一起:

  1. atomic // Default
  2. nonatomic
  3. < code>strong = keep // 默认
  4. weak = unsafe_unretained
  5. retain
  6. assign // 默认
  7. unsafe_unretained
  8. < code>copy
  9. readonly
  10. readwrite //

文章中默认 iOS中的变量属性属性或修饰符你可以找到上面提到的所有属性,那肯定会帮你。

  1. 原子

    • atomic 表示只有一个线程访问该变量(静态类型)。
    • atomic 是线程安全的。
    • 但是性能很慢
    • 原子是默认行为
    • 非垃圾收集环境中的原子访问器(即使用保留/释放/自动释放时)将使用锁来确保另一个线程不会干扰值的正确设置/获取。
    • 它实际上并不是一个关键字。

    示例:

     @property (retain) NSString *name; 
    
          @合成名称; 
      
  2. 非原子

    • nonatomic 表示多线程访问变量(动态类型)。
    • nonatomic 是线程不安全的。
    • 但性能很快
    • nonatomic 不是默认行为。 我们需要在 property 属性中添加 nonatomic 关键字。
    • 当两个不同的进程(线程)同时访问同一个变量时,可能会导致意外的行为。

    示例:

     @property (非原子,保留) NSString *name; 
    
          @合成名称; 
      

After reading so many articles, Stack Overflow posts and making demo applications to check variable property attributes, I decided to put all the attributes information together:

  1. atomic // Default
  2. nonatomic
  3. strong = retain // Default
  4. weak = unsafe_unretained
  5. retain
  6. assign // Default
  7. unsafe_unretained
  8. copy
  9. readonly
  10. readwrite // Default

In the article Variable property attributes or modifiers in iOS you can find all the above-mentioned attributes, and that will definitely help you.

  1. atomic

    • atomic means only one thread access the variable (static type).
    • atomic is thread safe.
    • But it is slow in performance
    • atomic is the default behavior
    • Atomic accessors in a non garbage collected environment (i.e. when using retain/release/autorelease) will use a lock to ensure that another thread doesn't interfere with the correct setting/getting of the value.
    • It is not actually a keyword.

    Example:

        @property (retain) NSString *name;
    
        @synthesize name;
    
  2. nonatomic

    • nonatomic means multiple thread access the variable (dynamic type).
    • nonatomic is thread-unsafe.
    • But it is fast in performance
    • nonatomic is NOT default behavior. We need to add the nonatomic keyword in the property attribute.
    • It may result in unexpected behavior, when two different process (threads) access the same variable at the same time.

    Example:

        @property (nonatomic, retain) NSString *name;
    
        @synthesize name;
    
说好的呢 2024-07-20 19:19:20

我找到了对原子和非原子属性的很好的解释 这里。 以下是相同的一些相关文本:

“原子”意味着它不能被分解。
在操作系统/编程术语中,原子函数调用是一种不能被中断的调用——整个函数必须被执行,并且在完成之前不能通过操作系统通常的上下文切换从CPU中换出。 以防万一您不知道:由于 CPU 一次只能做一件事,因此操作系统会将 CPU 的访问权轮流分配给所有正在运行的进程,从而给人一种错觉多任务处理。 CPU 调度程序可以(并且确实)在进程执行过程中的任何时刻中断进程 - 即使在函数调用中间。 因此,对于更新共享计数器变量之类的操作(其中两个进程可以尝试同时更新变量),它们必须“原子”执行,即每个更新操作必须在任何其他进程交换到该变量之前完整完成。 CPU。

所以我猜测在这种情况下原子意味着属性读取器方法不能被中断 - 实际上意味着该方法正在读取的变量不能在中途更改其值,因为其他一些线程/调用/function 被交换到 CPU 上。

由于原子变量不能被中断,因此它们在任何点所包含的值都保证(线程锁)未损坏,尽管确保此线程锁可以访问对他们来说要慢一些。 另一方面,非原子变量不提供此类保证,但确实提供了更快的访问速度。 总而言之,当您知道多个线程不会同时访问您的变量并加快速度时,请选择非原子

I found a pretty well put explanation of atomic and non-atomic properties here. Here's some relevant text from the same:

'atomic' means it cannot be broken down.
In OS/programming terms an atomic function call is one that cannot be interrupted - the entire function must be executed, and not swapped out of the CPU by the OS's usual context switching until it's complete. Just in case you didn't know: since the CPU can only do one thing at a time, the OS rotates access to the CPU to all running processes in little time-slices, to give the illusion of multitasking. The CPU scheduler can (and does) interrupt a process at any point in its execution - even in mid function call. So for actions like updating shared counter variables where two processes could try to update the variable at the same time, they must be executed 'atomically', i.e., each update action has to finish in its entirety before any other process can be swapped onto the CPU.

So I'd be guessing that atomic in this case means the attribute reader methods cannot be interrupted - in effect meaning that the variable(s) being read by the method cannot change their value half way through because some other thread/call/function gets swapped onto the CPU.

Because the atomic variables can not be interrupted, the value contained by them at any point is (thread-lock) guaranteed to be uncorrupted, although, ensuring this thread lock makes access to them slower. non-atomic variables, on the other hand, make no such guarantee but do offer the luxury of quicker access. To sum it up, go with non-atomic when you know your variables won't be accessed by multiple threads simultaneously and speed things up.

剧终人散尽 2024-07-20 19:19:20

原子:

原子保证对属性的访问将以原子方式执行。 例如,它总是返回一个完全初始化的对象,一个线程上属性的任何获取/设置都必须先完成,然后另一个线程才能访问它。

如果您想象以下函数同时在两个线程上发生,您就会明白为什么结果不会很好。

-(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 :

Atomic guarantees that access to the property will be performed in an atomic manner. E.g. it always return a fully initialised objects, any get/set of a property on one thread must complete before another can access it.

If you imagine the following function occurring on two threads at once you can see why the results would not be pretty.

-(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;
  }

  ...
}

Pros :
Return of fully initialised objects each time makes it best choice in case of multi-threading.

Cons :
Performance hit, makes execution a little slower

Non-Atomic :

Unlike Atomic, it doesn't ensure fully initialised object return each time.

Pros :
Extremely fast execution.

Cons :
Chances of garbage value in case of multi-threading.

傲世九天 2024-07-20 19:19:20

首先最简单的答案:你的第二个例子之间没有区别。 默认情况下,属性访问器是原子的。

非垃圾收集环境中的原子访问器(即使用保留/释放/自动释放时)将使用锁来确保另一个线程不会干扰值的正确设置/获取。

请参阅“Performance and Threading" Apple Objective-C 2.0 文档部分了解更多信息和创建多线程应用程序时的其他注意事项。

Easiest answer first: There's no difference between your second two examples. By default, property accessors are atomic.

Atomic accessors in a non garbage collected environment (i.e. when using retain/release/autorelease) will use a lock to ensure that another thread doesn't interfere with the correct setting/getting of the value.

See the "Performance and Threading" section of Apple's Objective-C 2.0 documentation for some more information and for other considerations when creating multi-threaded apps.

眼藏柔 2024-07-20 19:19:20

原子性意味着只有一个线程访问该变量(静态类型)。 Atomic是线程安全的,但速度很慢。

非原子意味着多个线程访问变量(动态类型)。 非原子是线程不安全的,但速度很快。

Atomic means only one thread accesses the variable (static type). Atomic is thread-safe, but it is slow.

Nonatomic means multiple threads access the variable (dynamic type). Nonatomic is thread-unsafe, but it is fast.

神也荒唐 2024-07-20 19:19:20

Atomic 是线程安全,它并且它很好地保证(不保证)无论有多少线程,都只提供锁定的值正在尝试访问同一区域。 当使用原子时,在该函数内编写的一段代码成为临界区的一部分,一次只能有一个线程执行。

它仅保证线程安全; 它不能保证这一点。 我的意思是你为你的车聘请了一位专业司机,但这并不能保证汽车不会发生事故。 然而,概率仍然是最小的。

原子 - 它无法被分解,因此结果是预期的。 对于非原子 - 当另一个线程访问内存区域时,它可以修改它,因此结果是意外的。

代码对话:

原子使属性的 getter 和 setter 线程安全。 例如,如果你写了:

self.myProperty = value;

是线程安全的。

[myArray addObject:@"Abc"] 

不是线程安全的。

Atomic is thread safe, it is slow and it well-assures (not guaranteed) that only the locked value is provided no matter how many threads are attempting access over the same zone. When using atomic, a piece of code written inside this function becomes the part of the critical section, to which only one thread can execute at a time.

It only assures the thread safety; it does not guarantee that. What I mean is you hire an expert driver for you car, still it doesn't guarantees car won't meet an accident. However, probability remains the slightest.

Atomic - it can't be broken down, so the result is expected. With nonatomic - when another thread access the memory zone it can modify it, so the result is unexpected.

Code Talk :

Atomic make getter and setter of the property thread safe. for example if u have written :

self.myProperty = value;

is thread safe.

[myArray addObject:@"Abc"] 

is NOT thread safe.

晨光如昨 2024-07-20 19:19:20

原子(默认)

原子是默认值:如果您不输入任何内容,您的属性就是
原子。 如果您尝试读取,则可以保证原子属性
它,你会得到一个有效的值。 它不做任何保证
关于这个值可能是什么,但你会得到好的数据,而不是
只是垃圾记忆。 如果您有多个
线程或多进程指向单个变量,一个
线程可以读取,另一个线程可以写入。 如果他们同时击中
此时,读取器线程一定会获得以下两个值之一:
无论是变更前还是变更后。 什么原子不
给你的是关于你的这些价值观中的哪一个的任何形式的保证
也许能得到。 原子确实经常与线程安全混淆,
这是不正确的。 你需要保证你的线程安全
其他方法。 然而,原子将保证,如果你尝试阅读,
你会得到某种价值。

非原子

另一方面,正如您可能猜到的那样,非原子只是意味着,
“不要做那些原子性的事情。” 你失去的是对你的保证
总是能拿回一些东西。 如果您尝试在中间阅读
write,你可以取回垃圾数据。 但是,另一方面,你去
快一点。 因为原子属性必须发挥一些魔力
为了保证您能返回一个值,它们会慢一些。 如果
这是您经常访问的属性,您可能想放弃
降至非原子,以确保您不会产生这样的速度
处罚。

在此处查看更多信息:https://realm.io/news/tmi-objective-c-property-attributes /

atomic (default)

Atomic is the default: if you don’t type anything, your property is
atomic. An atomic property is guaranteed that if you try to read from
it, you will get back a valid value. It does not make any guarantees
about what that value might be, but you will get back good data, not
just junk memory. What this allows you to do is if you have multiple
threads or multiple processes pointing at a single variable, one
thread can read and another thread can write. If they hit at the same
time, the reader thread is guaranteed to get one of the two values:
either before the change or after the change. What atomic does not
give you is any sort of guarantee about which of those values you
might get. Atomic is really commonly confused with being thread-safe,
and that is not correct. You need to guarantee your thread safety
other ways. However, atomic will guarantee that if you try to read,
you get back some kind of value.

nonatomic

On the flip side, non-atomic, as you can probably guess, just means,
“don’t do that atomic stuff.” What you lose is that guarantee that you
always get back something. If you try to read in the middle of a
write, you could get back garbage data. But, on the other hand, you go
a little bit faster. Because atomic properties have to do some magic
to guarantee that you will get back a value, they are a bit slower. If
it is a property that you are accessing a lot, you may want to drop
down to nonatomic to make sure that you are not incurring that speed
penalty.

See more here: https://realm.io/news/tmi-objective-c-property-attributes/

若水般的淡然安静女子 2024-07-20 19:19:20

没有这样的关键字“atomic”

@property(atomic, retain) UITextField *userName;

我们可以使用上面的内容,例如

@property(retain) UITextField *userName;

参见堆栈溢出问题我遇到问题如果我使用@property(atomic,retain)NSString *myString

There is no such keyword "atomic"

@property(atomic, retain) UITextField *userName;

We can use the above like

@property(retain) UITextField *userName;

See Stack Overflow question I am getting issues if I use @property(atomic,retain)NSString *myString.

べ映画 2024-07-20 19:19:20

默认原子,这意味着每当您使用该属性时,它都会降低性能,但它是线程安全的。 Objective-C 所做的是设置一个锁,因此只要执行 setter/getter,只有实际线程可以访问该变量。

具有 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的方法调用是。 但是如果你在 2 个不同的线程中同时使用 setter 和 getter,它也可能会被破坏!

The default is atomic, this means it does cost you performance whenever you use the property, but it is thread safe. What Objective-C does, is set a lock, so only the actual thread may access the variable, as long as the setter/getter is executed.

Example with MRC of a property with an ivar _internal:

[_internal lock]; //lock
id result = [[value retain] autorelease];
[_internal unlock];
return result;

So these last two are the same:

@property(atomic, retain) UITextField *userName;

@property(retain) UITextField *userName; // defaults to atomic

On the other hand does nonatomic add nothing to your code. So it is only thread safe if you code security mechanism yourself.

@property(nonatomic, retain) UITextField *userName;

The keywords doesn't have to be written as first property attribute at all.

Don't forget, this doesn't mean that the property as a whole is thread-safe. Only the method call of the setter/getter is. But if you use a setter and after that a getter at the same time with 2 different threads, it could be broken too!

欢你一世 2024-07-20 19:19:20
  • -Atomic 表示只有一个线程访问该变量(静态类型)。
  • -Atomic 是线程安全的。
  • -但性能较慢

如何声明:

由于原子性是默认的,

@property (retain) NSString *name;

并且在实现文件中

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”,

现在如果 *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 means only one thread access the variable(static type).
  • -Atomic is thread safe.
  • -but it is slow in performance

How to declare:

As atomic is default so,

@property (retain) NSString *name;

AND in implementation file

self.name = @"sourov";

Suppose a task related to three properties are

 @property (retain) NSString *name;
 @property (retain) NSString *A;
 @property (retain) NSString *B;
 self.name = @"sourov";

All properties work parallelly (like asynchronously).

If you call "name" from thread A,

And

At the same time if you call

[self setName:@"Datta"]

from thread B,

Now If *name property is nonatomic then

  • It will return value "Datta" for A
  • It will return value "Datta" for B

Thats why non atomic is called thread unsafe But but it is fast in performance because of parallel execution

Now If *name property is atomic

  • It will ensure value "Sourov" for A
  • Then It will return value "Datta" for B

That's why atomic is called thread Safe and
That's why it is called read-write safe

Such situation operation will perform serially.
And Slow in performance

- Nonatomic means multiple thread access the variable(dynamic type).

- Nonatomic is thread unsafe.

- but it is fast in performance

-Nonatomic is NOT default behavior, we need to add nonatomic keyword in property attribute.

For In Swift
Confirming that Swift properties are nonatomic in the ObjC sense. One reason is so you think about whether per-property atomicity is sufficient for your needs.

Reference: https://forums.developer.apple.com/thread/25642

Fro more info please visit the website
http://rdcworld-iphone.blogspot.in/2012/12/variable-property-attributes-or.html

清风无影 2024-07-20 19:19:20

如果您在多线程代码中使用属性,那么您将能够看到非原子属性和原子属性之间的区别。 非原子比原子更快,并且原子是线程安全的,而不是非原子。

Vijayendra Tripathi 已经给出了多线程环境的示例。

If you are using your property in multi-threaded code then you would be able to see the difference between nonatomic and atomic attributes. Nonatomic is faster than atomic and atomic is thread-safe, not nonatomic.

Vijayendra Tripathi has already given an example for a multi-threaded environment.

梦纸 2024-07-20 19:19:20

开始之前:您必须知道,内存中的每个对象都需要从内存中释放,以便发生新的写入操作。 你不能像在纸上那样简单地在某物上书写。 您必须首先擦除(释放)它,然后才能在上面写入。 如果此时擦除已完成(或完成一半)并且尚未写入任何内容(或写入一半),而您尝试读取它可能会出现很大问题! 原子和非原子可以帮助您以不同的方式处理这个问题。

首先阅读这个问题,然后阅读Bbum 的回答。 另外,再看看我的总结。


原子将始终保证

  • 如果两个不同的人想要同时读写,你的论文不会被烧毁! --> 即使在竞争条件下,您的应用程序也永远不会崩溃。
  • 如果一个人正在尝试写,并且只写了要写的8个字母中的4个,那么中间就无法阅读,只有写完所有8个字母才能阅读 --> 在“仍在写入的线程”上不会发生读取(获取),即如果有 8 个字节要写入,而只写入了 4 个字节——到那时,您就不允许从中读取。 但既然我说过它不会崩溃,那么它就会从自动释放对象的值中读取。
  • 如果写作之前,您已经擦掉了之前写在纸上的内容,然后有人想读您可以仍然可以阅读。 如何? 您将从类似于 Mac OS 垃圾箱的内容中读取内容(因为垃圾箱尚未 100% 被删除...它处于不确定状态)---> 如果 ThreadA 要读取,而 ThreadB 已释放写入权限,您可以从 ThreadB 最终完全写入的值中获取一个值,或者从自动释放池中获取一些值。

保留计数是 Objective-C 中管理内存的方式。
当你创建一个对象时,它的保留计数为1。当你发送
一个对象收到保留消息后,其保留计数会加 1。当
您向对象发送释放消息,其保留计数会减少
1. 当你向一个对象发送自动释放消息时,它的保留计数
在未来的某个阶段减1。 如果一个对象保留
count 减少到 0,它被释放。

  • 原子保证线程安全,尽管它对于实现线程安全很有用。 线程安全与您编写代码的方式/正在读取/写入的线程队列相关。 它仅保证多线程不崩溃。

什么?! 多线程和线程安全有何不同?

是的。 多线程意味着:多个线程可以同时读取共享的数据,并且我们不会崩溃,但它不能保证您不会读取非自动释放的值。 有了线程安全,就可以保证你读到的内容不会被自动释放。
默认情况下,我们不将所有内容设为原子的原因是,存在性能成本,并且对于大多数事情来说,并不真正需要线程安全。 我们代码的某些部分需要它,对于这几个部分,我们需要使用锁、互斥锁或同步以线程安全的方式编写代码。


nonatomic

  • 由于没有像 Mac OS 垃圾箱这样的东西,所以没有人关心你是否总是得到一个值(<-- 这可能会导致崩溃),也没有人关心是否有人试图读到你的写作中途(虽然在记忆中写到一半与在纸上写到一半有很大不同,在记忆中它可能会给你一个以前疯狂愚蠢的值,而在纸上你只能看到一半)写了什么) --> 不保证不崩溃,因为它不使用自动释放机制。
  • 不保证读取完整的写入值!
  • 比原子更快

总体而言,它们在两个方面有所不同:

  • 是否由于有或没有自动释放池而崩溃。

  • 在“尚未完成的写入或空值”中间读取,或者不允许并且仅允许在值完全写入时读取。

Before you begin: You must know that every object in memory needs to be deallocated from memory for a new writer to happen. You can't just simply write on top of something as you do on paper. You must first erase (dealloc) it and then you can write onto it. If at the moment that the erase is done (or half done) and nothing has yet been wrote (or half wrote) and you try to read it could be very problematic! Atomic and nonatomic help you treat this problem in different ways.

First read this question and then read Bbum's answer. In addition, then read my summary.


atomic will ALWAYS guarantee

  • If two different people want to read and write at the same time, your paper won't just burn! --> Your application will never crash, even in a race condition.
  • If one person is trying to write and has only written 4 of the 8 letters to write, then no can read in the middle, the reading can only be done when all 8 letters is written --> No read(get) will happen on 'a thread that is still writing', i.e. if there are 8 bytes to bytes to be written, and only 4 bytes are written——up to that moment, you are not allowed to read from it. But since I said it won't crash then it would read from the value of an autoreleased object.
  • If before writing you have erased that which was previously written on paper and then someone wants to read you can still read. How? You will be reading from something similar to Mac OS Trash bin ( as Trash bin is not still 100% erased...it's in a limbo) ---> If ThreadA is to read while ThreadB has already deallocated to write, you would get a value from either the final fully written value by ThreadB or get something from autorelease pool.

Retain counts are the way in which memory is managed in Objective-C.
When you create an object, it has a retain count of 1. When you send
an object a retain message, its retain count is incremented by 1. When
you send an object a release message, its retain count is decremented
by 1. When you send an object an autorelease message, its retain count
is decremented by 1 at some stage in the future. If an objectʼs retain
count is reduced to 0, it is deallocated.

  • Atomic doesn't guarantee thread safety, though it's useful for achieving thread safety. Thread Safety is relative to how you write your code/ which thread queue you are reading/writing from. It only guarantees non-crashable multithreading.

What?! Are multithreading and thread safety different?

Yes. Multithreading means: multiple threads can read a shared piece of data at the same time and we will not crash, yet it doesn't guarantee that you aren't reading from a non-autoreleased value. With thread safety, it's guaranteed that what you read is not auto-released.
The reason that we don't make everything atomic by default is, that there is a performance cost and for most things don't really need thread safety. A few parts of our code need it and for those few parts, we need to write our code in a thread-safe way using locks, mutex or synchronization.


nonatomic

  • Since there is no such thing like Mac OS Trash Bin, then nobody cares whether or not you always get a value (<-- This could potentially lead to a crash), nor anybody cares if someone tries to read halfway through your writing (although halfway writing in memory is very different from halfway writing on paper, on memory it could give you a crazy stupid value from before, while on paper you only see half of what's been written) --> Doesn't guarantee to not crash, because it doesn't use autorelease mechanism.
  • Doesn't guarantee full written values to be read!
  • Is faster than atomic

Overall they are different in 2 aspects:

  • Crashing or not because of having or not having an autorelease pool.

  • Allowing to be read right in the middle of a 'not yet finished write or empty value' or not allowing and only allowing to read when the value is fully written.

怪异←思 2024-07-20 19:19:20

原子性
原子(默认)

原子是默认值:如果您不输入任何内容,您的属性就是
原子。 如果您尝试读取,则可以保证原子属性
它,你会得到一个有效的值。 它不做任何保证
关于这个值可能是什么,但你会得到好的数据,而不是
只是垃圾记忆。 如果您有多个
线程或多进程指向单个变量,一个
线程可以读取,另一个线程可以写入。 如果他们同时击中
此时,读取器线程一定会获得以下两个值之一:
无论是变更前还是变更后。 什么原子不
给你的是关于你的这些价值观中的哪一个的任何形式的保证
也许能得到。 原子确实经常与线程安全混淆,
这是不正确的。 你需要保证你的线程安全
其他方法。 然而,原子将保证,如果你尝试阅读,
你会得到某种价值。

非原子

另一方面,正如您可能猜到的那样,非原子只是意味着,
“不要做那些原子性的事情。” 你失去的是对你的保证
总是能拿回一些东西。 如果您尝试在中间阅读
write,你可以取回垃圾数据。 但是,另一方面,你去
快一点。 因为原子属性必须发挥一些魔力
为了保证您能返回一个值,它们会慢一些。 如果
这是您经常访问的属性,您可能想放弃
降至非原子,以确保您不会出现该速度
惩罚。 访问

https://academy.realm.io/posts/tmi- Objective-c-property-attributes/

原子性属性属性(原子和非原子)不会反映在相应的 Swift 属性声明中,但当导入的属性为从 Swift 访问。

它在 Swift 使用时将保持原子性。

所以——如果你在 Objective-C 中定义了一个原子属性,
https://medium.com/@YogevSitton/atomic -vs-非原子属性-crash-course-d11c23f4366c

Atomicity
atomic (default)

Atomic is the default: if you don’t type anything, your property is
atomic. An atomic property is guaranteed that if you try to read from
it, you will get back a valid value. It does not make any guarantees
about what that value might be, but you will get back good data, not
just junk memory. What this allows you to do is if you have multiple
threads or multiple processes pointing at a single variable, one
thread can read and another thread can write. If they hit at the same
time, the reader thread is guaranteed to get one of the two values:
either before the change or after the change. What atomic does not
give you is any sort of guarantee about which of those values you
might get. Atomic is really commonly confused with being thread-safe,
and that is not correct. You need to guarantee your thread safety
other ways. However, atomic will guarantee that if you try to read,
you get back some kind of value.

nonatomic

On the flip side, non-atomic, as you can probably guess, just means,
“don’t do that atomic stuff.” What you lose is that guarantee that you
always get back something. If you try to read in the middle of a
write, you could get back garbage data. But, on the other hand, you go
a little bit faster. Because atomic properties have to do some magic
to guarantee that you will get back a value, they are a bit slower. If
it is a property that you are accessing a lot, you may want to drop
down to nonatomic to make sure that you are not incurring that speed
penalty. Access

courtesy https://academy.realm.io/posts/tmi-objective-c-property-attributes/

Atomicity property attributes (atomic and nonatomic) are not reflected in the corresponding Swift property declaration, but the atomicity guarantees of the Objective-C implementation still hold when the imported property is accessed from Swift.

So — if you define an atomic property in Objective-C it will remain atomic when used by Swift.

courtesy
https://medium.com/@YogevSitton/atomic-vs-non-atomic-properties-crash-course-d11c23f4366c

动听の歌 2024-07-20 19:19:20

原子属性确保无论有多少线程正在执行 getter 和 getter 操作,都保留完全初始化的值。 设置器在其上。

非原子属性指定合成访问器只是直接设置或返回一个值,不能保证从不同线程同时访问同一值时会发生什么。

The atomic property ensures to retain a fully initialised value irrespective of how many threads are doing getter & setter on it.

The nonatomic property specifies that synthesized accessors simply set or return a value directly, with no guarantees about what happens if that same value is accessed simultaneously from different threads.

野却迷人 2024-07-20 19:19:20

原子性意味着一次只有一个线程可以访问该变量(静态类型)。 Atomic是线程安全的,但速度很慢。

非原子意味着多个线程可以同时访问该变量(动态类型)。 非原子是线程不安全的,但速度很快。

Atomic means only one thread can access the variable at a time (static type). Atomic is thread-safe, but it is slow.

Nonatomic means multiple threads can access the variable at same time (dynamic type). Nonatomic is thread-unsafe, but it is fast.

空心↖ 2024-07-20 19:19:20

事实是他们使用自旋锁来实现原子属性。 代码如下:

 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);
    }

The truth is that they use spin lock to implement atomic property. The code as below:

 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);
    }
指尖凝香 2024-07-20 19:19:20

在一行中:

Atomic 是线程安全的。 Nonatomic 是线程不安全的。

In a single line:

Atomic is thread safe. Nonatomic is thread-unsafe.

拍不死你 2024-07-20 19:19:20

如果您使用原子性,则意味着线程将是安全且只读的。 如果使用nonatomic,则意味着多个线程访问该变量,是线程不安全的,但执行速度很快,完成了读写操作; 这是一个动态类型。

If you are using atomic, it means the thread will be safe and read-only. If you are using nonatomic, it means the multiple threads access the variable and is thread unsafe, but it is executed fast, done a read and write operations; this is a dynamic type.

原子性:通过使用 NSLOCK 锁定线程来确保线程安全。

非原子:不确保线程安全,因为没有线程锁定机制。

Atomic: Ensure thread-safety by locking the thread using NSLOCK.

Non atomic: Doesn't ensure thread-safety as there is no thread-locking mechanism.

め七分饶幸 2024-07-20 19:19:20

为了简化整个混乱,让我们了解互斥锁。

互斥锁,顾名思义,锁定对象的可变性。 因此,如果该对象被一个类访问,则其他类就不能访问同一个对象。

在 iOS 中,@sychronise 还提供了互斥锁。现在它以 FIFO 模式提供服务,并确保流程不会受到共享同一实例的两个类的影响。 但是,如果任务位于主线程上,请避免使用原子属性访问对象,因为它可能会占用您的 UI 并降低性能。

To simplify the entire confusion, let us understand mutex lock.

Mutex lock, as per the name, locks the mutability of the object. So if the object is accessed by a class, no other class can access the same object.

In iOS, @sychronise also provides the mutex lock .Now it serves in FIFO mode and ensures the flow is not affected by two classes sharing the same instance. However, if the task is on main thread, avoid accessing object using atomic properties as it may hold your UI and degrade the performance.

赠意 2024-07-20 19:19:20

在 Objective-C 中,原子属性的实现允许从不同线程安全地读取和写入属性。 对于非原子属性,当同时写入新值时,可以释放读取值的底层指针。

原子性意味着只有一个线程访问该变量(静态类型)。 Atomic是线程安全的,但速度很慢。 非原子意味着多个线程访问变量(动态类型)。非原子是线程不安全的,但速度很快。

In Objective-C the implementation of an atomic property allows properties to be safely read and written from different threads. For nonatomic properties, the underlying pointer of a read value could be released when a new value is being written at the same time.

Atomic means only one thread accesses the variable (static type). Atomic is thread-safe, but it is slow. Nonatomic means multiple threads access the variable (dynamic type). Nonatomic is thread-unsafe, but it is fast.

九局 2024-07-20 19:19:20

原子属性:- 当一个变量分配有原子属性时,这意味着它只有一个线程访问,并且它将是线程安全的,并且从性能角度来看会很慢,将具有默认行为。

非原子属性:- 当一个变量分配有非原子属性时,这意味着它具有多线程访问,并且它不是线程安全的,并且从性能角度来看会很快,将具有默认行为,并且当两个不同的线程时想要同时访问变量会给出意想不到的结果。

Atomic properties :- When a variable assigned with atomic property that means it has only one thread access and it will be thread safe and will be slow in performance perspective, will have default behaviour.

Non Atomic Properties :- When a variable assigned with nonatomic property that means it has multi thread access and it will not be thread safe and will be fast in performance perspective, will have default behaviour and when two different threads want to access variable at same time it will give unexpected results.

蘸点软妹酱 2024-07-20 19:19:19

最后两个是相同的; “atomic”是默认行为(请注意,它实际上不是关键字;它仅通过缺少 nonatomic 来指定 - atomic在最新版本的 llvm/clang 中添加为关键字)。

假设您正在 @synthesizing 方法实现,原子与非原子会更改生成的代码。 如果您正在编写自己的 setter/getter,原子/非原子/保留/分配/复制只是建议性的。 (注意:@synthesize 现在是 LLVM 最新版本中的默认行为。也无需声明实例变量;它们也会自动合成,并且名称前会添加 _以防止意外直接访问)。

使用“atomic”,合成的 setter/getter 将确保始终从 getter 返回整个值或由 setter 设置,无论任何其他线程上的 setter 活动如何。 也就是说,如果线程 A 位于 getter 中间,而线程 B 调用 setter,则实际可行的值(很可能是自动释放的对象)将返回给 A 中的调用者。

在非原子中代码>,不做这样的保证。 因此,nonatomic 比“atomic”快得多。

“原子”所做的是对线程安全做出任何保证。 如果线程 A 与线程 B 和 C 同时调用 getter,同时线程 B 和 C 使用不同的值调用 setter,则线程 A 可能会获取返回的三个值中的任何一个 - 调用任何 setter 之前的值或传递到 setter 的值之一同样,该对象最终可能会得到 B 或 C 中的值,但无法判断。

确保数据完整性(多线程编程的主要挑战之一)是通过其他方式实现的。

除此之外:

当多个依赖属性发挥作用时,单个属性的原子性也无法保证线程安全。

考虑:

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

在这种情况下,线程 A 可以通过调用 setFirstName: 然后调用 setLastName: 来重命名该对象。 同时,线程 B 可以在线程 A 的两次调用之间调用 fullName,并将收到新的名字和旧的姓氏。

为了解决这个问题,您需要一个事务模型。 即,某种其他类型的同步和/或排除,允许在更新依赖属性时排除对fullName 的访问。

The last two are identical; "atomic" is the default behavior (note that it is not actually a keyword; it is specified only by the absence of nonatomic -- atomic was added as a keyword in recent versions of llvm/clang).

Assuming that you are @synthesizing the method implementations, atomic vs. non-atomic changes the generated code. If you are writing your own setter/getters, atomic/nonatomic/retain/assign/copy are merely advisory. (Note: @synthesize is now the default behavior in recent versions of LLVM. There is also no need to declare instance variables; they will be synthesized automatically, too, and will have an _ prepended to their name to prevent accidental direct access).

With "atomic", the synthesized setter/getter will ensure that a whole value is always returned from the getter or set by the setter, regardless of setter activity on any other thread. That is, if thread A is in the middle of the getter while thread B calls the setter, an actual viable value -- an autoreleased object, most likely -- will be returned to the caller in A.

In nonatomic, no such guarantees are made. Thus, nonatomic is considerably faster than "atomic".

What "atomic" does not do is make any guarantees about thread safety. If thread A is calling the getter simultaneously with thread B and C calling the setter with different values, thread A may get any one of the three values returned -- the one prior to any setters being called or either of the values passed into the setters in B and C. Likewise, the object may end up with the value from B or C, no way to tell.

Ensuring data integrity -- one of the primary challenges of multi-threaded programming -- is achieved by other means.

Adding to this:

atomicity of a single property also cannot guarantee thread safety when multiple dependent properties are in play.

Consider:

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

In this case, thread A could be renaming the object by calling setFirstName: and then calling setLastName:. In the meantime, thread B may call fullName in between thread A's two calls and will receive the new first name coupled with the old last name.

To address this, you need a transactional model. I.e. some other kind of synchronization and/or exclusion that allows one to exclude access to fullName while the dependent properties are being updated.

太阳哥哥 2024-07-20 19:19:19

Apple 的文档对此进行了解释,但以下是实际发生情况的一些示例。

请注意,没有“atomic”关键字,如果不指定“nonatomic”,则该属性是原子的,但显式指定“atomic”会导致错误。

如果不指定“ nonatomic”,则该属性是原子的,但如果您愿意,您仍然可以在最新版本中显式指定“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_;
    }
}

基本上,原子版本必须获取锁以保证线程安全,并且还会增加对象上的引用计数(以及自动释放计数以平衡它),以便保证调用者存在对象,否则如果另一个线程正在设置该值,则存在潜在的竞争条件,导致引用计数下降到 0。

实际上,这些东西的工作方式有大量不同的变体,具体取决于是否属性是标量值或对象,以及保留、复制、只读、非原子等如何交互。 一般来说,属性合成器只知道如何为所有组合做“正确的事情”。

This is explained in Apple's documentation, but below are some examples of what is actually happening.

Note that there is no "atomic" keyword, if you do not specify "nonatomic", then the property is atomic, but specifying "atomic" explicitly will result in an error.

If you do not specify "nonatomic", then the property is atomic, but you can still specify "atomic" explicitly in recent versions if you want to.

//@property(nonatomic, retain) UITextField *userName;
//Generates roughly

- (UITextField *) userName {
    return userName;
}

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

Now, the atomic variant is a bit more complicated:

//@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_;
    }
}

Basically, the atomic version has to take a lock in order to guarantee thread safety, and also is bumping the ref count on the object (and the autorelease count to balance it) so that the object is guaranteed to exist for the caller, otherwise there is a potential race condition if another thread is setting the value, causing the ref count to drop to 0.

There are actually a large number of different variants of how these things work depending on whether the properties are scalar values or objects, and how retain, copy, readonly, nonatomic, etc interact. In general the property synthesizers just know how to do the "right thing" for all combinations.

︶葆Ⅱㄣ 2024-07-20 19:19:19

原子

  • 是默认行为,
  • 将确保当前进程由 CPU 完成,在另一个进程访问变量之前
  • 速度不快,因为它确保进程完全完成

非原子

  • 不是
  • 更快的默认行为(对于合成代码,即,对于使用 @property 和 @synthesize 创建的变量),
  • 非线程安全可能会导致意外行为
  • 当两个不同的进程同时访问同一个变量时,

Atomic

  • is the default behavior
  • will ensure the present process is completed by the CPU, before another process accesses the variable
  • is not fast, as it ensures the process is completed entirely

Non-Atomic

  • is NOT the default behavior
  • faster (for synthesized code, that is, for variables created using @property and @synthesize)
  • not thread-safe
  • may result in unexpected behavior, when two different process access the same variable at the same time
淡忘如思 2024-07-20 19:19:19

理解差异的最佳方法是使用以下示例。

假设有一个名为“name”的原子字符串属性,如果从线程 A 调用 [self setName:@"A"],则调用 [self setName:@"B"]< /code> 从线程 B 调用,并从线程 C 调用 [self name],那么不同线程上的所有操作将串行执行,这意味着如果一个线程正在执行 setter 或 getter,那么其他线程将执行等待。

这使得属性“name”读/写安全,但如果另一个线程 D 同时调用 [name release] 那么此操作可能会产生崩溃,因为这里不涉及 setter/getter 调用。 这意味着对象是读/写安全的(ATOMIC),但不是线程安全的,因为另一个线程可以同时向该对象发送任何类型的消息。 开发人员应该确保此类对象的线程安全。

如果属性“name”是非原子的,则上例中的所有线程 - A、B、C 和 D 将同时执行,产生任何不可预测的结果。 在原子的情况下,A、B或C之一将首先执行,但D仍然可以并行执行。

The best way to understand the difference is using the following example.

Suppose there is an atomic string property called "name", and if you call [self setName:@"A"] from thread A, call [self setName:@"B"] from thread B, and call [self name] from thread C, then all operations on different threads will be performed serially which means if one thread is executing a setter or getter, then other threads will wait.

This makes property "name" read/write safe, but if another thread, D, calls [name release] simultaneously then this operation might produce a crash because there is no setter/getter call involved here. Which means an object is read/write safe (ATOMIC), but not thread-safe as another threads can simultaneously send any type of messages to the object. The developer should ensure thread-safety for such objects.

If the property "name" was nonatomic, then all threads in above example - A,B, C and D will execute simultaneously producing any unpredictable result. In case of atomic, either one of A, B or C will execute first, but D can still execute in parallel.

豆芽 2024-07-20 19:19:19

这个问题的其他优秀答案已经很好地定义了语法和语义。 由于执行性能没有详细说明,我将添加我的答案。

这三个之间的功能区别是什么?

我一直认为原子作为默认值非常好奇。 在我们工作的抽象级别,使用类的原子属性作为实现 100% 线程安全的工具是一种特殊情况。 对于真正正确的多线程程序,几乎肯定需要程序员的干预。 同时,性能特征和执行尚未深入详细说明。 多年来,我编写了一些大量的多线程程序,我一直将我的属性声明为非原子的,因为原子对于任何目的都是不明智的。 在讨论原子和非原子属性的细节时 这个问题,我做了一些分析,遇到了一些奇怪的结果。

执行

好的。 我要澄清的第一件事是锁定实现是实现定义的和抽象的。 Louis 在他的示例中使用了 @synchronized(self) ——我认为这是一个常见的混乱来源。 该实现实际上并未使用@synchronized(self); 它使用对象级自旋锁。 Louis 的插图非常适合使用我们都熟悉的结构进行高级插图,但重要的是要知道它不使用 @synchronized(self)

另一个区别是原子属性将在 getter 中保留/释放循环您的对象。

性能

这是有趣的部分:在无竞争(例如单线程)情况下使用原子属性访问的性能在某些情况下可能非常快。 在不太理想的情况下,使用原子访问的开销可能是非原子访问开销的 20 倍以上。 而使用 7 个线程的有争议情况对于三字节结构 (2.2 GHz 核心 i7 四核,x86_64)。 三字节结构是一个非常慢的属性的示例。

有趣的旁注:三字节结构的用户定义访问器比合成原子访问器快 52 倍; 或合成非原子访问器速度的 84%。

有争议案件中的对象也可能超过 50 次。

由于实施过程中存在大量优化和变化,因此很难衡量这些环境中的实际影响。 您可能经常听到类似“相信它,除非您分析并发现它是一个问题”之类的话。 由于抽象级别的原因,实际上很难衡量实际影响。 从配置文件中收集实际成本可能非常耗时,而且由于抽象,非常不准确。 同样,ARC 与 MRC 可以产生很大的不同。

因此,让我们退一步,关注属性访问的实现,我们将包括诸如 objc_msgSend 之类的常见嫌疑人,并检查许多现实世界的高级结果在无争议情况下调用NSString getter(值以秒为单位):

  • MRC | 非原子| 手动实现的吸气剂:2
  • MRC | 非原子| 合成吸气剂:7
  • MRC | 原子| 合成吸气剂:47
  • ARC | 非原子| 在此处添加引用计数循环)
  • 合成吸气剂:38(注意: ARC 原子| 合成吸气剂:47

正如您可能已经猜到的那样,引用计数活动/循环是原子和 ARC 下的重要贡献者。 您还会在有争议的案件中看到更大的差异。

尽管我非常关注性能,但我仍然说语义第一!。 与此同时,对于许多项目来说,性能并不是最重要的。 然而,了解您所使用的技术的执行细节和成本当然不会有什么坏处。 您应该根据您的需求、目的和能力使用正确的技术。 希望这将为您节省几个小时的比较时间,并帮助您在设计程序时做出更明智的决定。

The syntax and semantics are already well-defined by other excellent answers to this question. Because execution and performance are not detailed well, I will add my answer.

What is the functional difference between these 3?

I'd always considered atomic as a default quite curious. At the abstraction level we work at, using atomic properties for a class as a vehicle to achieve 100% thread-safety is a corner case. For truly correct multithreaded programs, intervention by the programmer is almost certainly a requirement. Meanwhile, performance characteristics and execution have not yet been detailed in depth. Having written some heavily multithreaded programs over the years, I had been declaring my properties as nonatomic the entire time because atomic was not sensible for any purpose. During discussion of the details of atomic and nonatomic properties this question, I did some profiling encountered some curious results.

Execution

Ok. The first thing I would like to clear up is that the locking implementation is implementation-defined and abstracted. Louis uses @synchronized(self) in his example -- I have seen this as a common source of confusion. The implementation does not actually use @synchronized(self); it uses object level spin locks. Louis's illustration is good for a high-level illustration using constructs we are all familiar with, but it's important to know it does not use @synchronized(self).

Another difference is that atomic properties will retain/release cycle your objects within the getter.

Performance

Here's the interesting part: Performance using atomic property accesses in uncontested (e.g. single-threaded) cases can be really very fast in some cases. In less than ideal cases, use of atomic accesses can cost more than 20 times the overhead of nonatomic. While the Contested case using 7 threads was 44 times slower for the three-byte struct (2.2 GHz Core i7 Quad Core, x86_64). The three-byte struct is an example of a very slow property.

Interesting side note: User-defined accessors of the three-byte struct were 52 times faster than the synthesized atomic accessors; or 84% the speed of synthesized nonatomic accessors.

Objects in contested cases can also exceed 50 times.

Due to the number of optimizations and variations in implementations, it's quite difficult to measure real-world impacts in these contexts. You might often hear something like "Trust it, unless you profile and find it is a problem". Due to the abstraction level, it's actually quite difficult to measure actual impact. Gleaning actual costs from profiles can be very time consuming, and due to abstractions, quite inaccurate. As well, ARC vs MRC can make a big difference.

So let's step back, not focussing on the implementation of property accesses, we'll include the usual suspects like objc_msgSend, and examine some real-world high-level results for many calls to a NSString getter in uncontested cases (values in seconds):

  • MRC | nonatomic | manually implemented getters: 2
  • MRC | nonatomic | synthesized getter: 7
  • MRC | atomic | synthesized getter: 47
  • ARC | nonatomic | synthesized getter: 38 (note: ARC's adding ref count cycling here)
  • ARC | atomic | synthesized getter: 47

As you have probably guessed, reference count activity/cycling is a significant contributor with atomics and under ARC. You would also see greater differences in contested cases.

Although I pay close attention to performance, I still say Semantics First!. Meanwhile, performance is a low priority for many projects. However, knowing execution details and costs of technologies you use certainly doesn't hurt. You should use the right technology for your needs, purposes, and abilities. Hopefully this will save you a few hours of comparisons, and help you make a better informed decision when designing your programs.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文