原子和非原子属性的区别是什么?

时间:2022-09-01 21:01:55

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?

这三者之间的操作差异是什么?

26 个解决方案

#1


1652  

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).

最后两个是相同的;“原子”是默认行为(请注意,它实际上不是关键字;它只在没有非原子的情况下指定——在最近版本的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).

假设您是@ synzing方法实现,原子vs非原子更改生成的代码。如果您正在编写自己的setter/getter,那么原子/非原子/保留/分配/复制仅仅是一个建议。(注意:@synthesize现在是LLVM最新版本的默认行为。也不需要声明实例变量;它们也会被自动合成,并且会有一个前缀以防止意外的直接访问。

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.

使用“原子”,合成的setter/getter将确保所有值始终从getter中返回,或者由setter设置,而不考虑任何其他线程上的setter活动。也就是说,如果线程A位于getter的中间,而线程B调用setter,那么一个实际可行的值——很可能是一个autoreleatedobject——将会返回给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.

“原子”不做的是对线程安全做任何保证。如果线程与线程同时调用getter B和C调用setter与不同价值观,线程A可能会返回的三个值中的任何一个,前一个被调用setter或者值传递到setter的B和C .同样,价值的对象可能会从B或C,无法告诉。

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.

在这种情况下,线程A可以通过调用setFirstName来重命名对象:然后调用setLastName:。与此同时,线程B可能在线程A的两个调用之间调用fullName,并将接收新名称和旧名称。

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.

要解决这个问题,您需要一个事务模型。也就是一些其他类型的同步和/或排除,允许一个人在依赖属性被更新时不允许访问fullName。

#2


340  

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.

这是在苹果的文档中解释的,但下面是一些实际发生的例子。注意,没有“原子”关键字,如果您没有指定“nonatomic”,那么属性是原子的,但是显式地指定“原子”将导致错误。

//@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.

基本上,原子版本必须采取一个锁来保证线程安全,也是撞裁判依靠对象(和autorelease数到平衡),对象是保证调用者的存在,否则如果另一个线程是一个潜在的竞态条件设置值,导致裁判数降至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.

实际上,根据属性是标量值还是对象,以及如何保持、复制、只读、非原子等交互,有很多不同的变体。一般来说,属性合成器只知道如何为所有组合做“正确的事情”。

#3


146  

Atomic

  • is the default behavior
  • 是默认行为
  • will ensure the present process is completed by the CPU, before another process accesses the variable
  • 将确保当前进程由CPU完成,然后另一个进程访问该变量?
  • 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)
  • 更快(对于合成的代码,即使用@property和@synthesize创建的变量)
  • not thread-safe
  • 非线程安全
  • may result in unexpected behavior, when two different process access the same variable at the same time
  • 当两个不同的进程同时访问同一个变量时,可能会导致意外的行为?

#4


123  

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.

假设有一个原子字符串属性称为“名称”,如果你叫(自我setName:@“A”)从线程,叫(自我setName:@“B”)从线程B,C并从线程调用(自己的名字),然后所有操作在不同的线程将执行连续这意味着如果一个线程正在执行一个setter和getter,那么其他线程会等待。

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.

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

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.

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

#5


108  

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.

我一直认为原子是一种默认,很奇怪。在抽象级别上,我们使用一个类的原子属性作为实现100%线程安全的工具。对于真正正确的多线程程序,程序员的干预几乎是必需的。与此同时,性能特征和执行还没有详细的深入。多年来,我编写了一些非常多线程的程序,我一直在声明我的属性是非原子性的,因为原子对任何目的都不敏感。在讨论原子和非原子属性的细节时,我做了一些分析,遇到了一些奇怪的结果。

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).

好的。首先我要澄清的是,锁定实现是实现定义和抽象的。路易斯在他的例子中使用@synchronized(self)——我把这看作是一个常见的混乱来源。实现并不实际使用@synchronized(self);它使用对象级旋转锁。Louis的插图对于使用我们都熟悉的构造来说是很好的,但是重要的是知道它不使用@synchronized(self)。

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

另一个区别是,原子属性将在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.

这里有一个有趣的部分:在一些情况下,在无争用(例如单线程)情况下使用原子属性访问的性能可能非常快。在不太理想的情况下,使用原子访问的开销可能超过非原子访问开销的20倍。在有争议的情况下,使用7个线程的3字节结构(2.2 GHz Core i7 Quad Core, x86_64)的速度要慢44倍。三字节结构是一个非常慢的属性的例子。

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.

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

Objects in contested cases can also exceed 50 times.

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

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.

由于实现的优化和变化,在这些上下文中测量实际的影响是相当困难的。你可能经常听到类似“相信它,除非你个人资料,发现它是一个问题”之类的东西。由于抽象级别,实际上很难测量实际的影响。从概要文件中收集实际成本可能非常耗时,而且由于抽象,非常不准确。同样,ARC和MRC可以产生很大的不同。

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

因此,让我们回过头来,不关注属性访问的实现,我们将包括像objc_msgSend这样的常见疑点,并检查一些在无争议的情况下对NSString getter的许多调用的实际高级结果(以秒为单位):

  • MRC | nonatomic | manually implemented getters: 2
  • MRC |非原子|手动执行getters: 2。
  • MRC | nonatomic | synthesized getter: 7
  • MRC |非原子|合成的吸气剂:7。
  • MRC | atomic | synthesized getter: 47
  • MRC |原子|合成吸气剂:47。
  • ARC | nonatomic | synthesized getter: 38 (note: ARC's adding ref count cycling here)
  • |非原子|合成的getter: 38(注:ARC在这里添加ref count循环)
  • ARC | atomic | synthesized getter: 47
  • ARC |原子|合成吸气剂: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.

虽然我关注性能,但我还是先说语义!与此同时,对于许多项目来说,性能是一个低优先级。然而,了解执行细节和使用的技术成本当然不会有坏处。您应该使用正确的技术来满足您的需求、目的和能力。希望这会为您节省几个小时的比较,并帮助您在设计程序时做出更明智的决定。

#6


88  

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 .

不像nonatomic那样快,因为nonatomic在运行时不需要任何监视程序。

Where to use nonatomic:

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

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

#7


67  

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.

“原子”意味着它不能被分解。在OS/编程术语中,一个原子函数调用是一个不能被中断的函数——必须执行整个函数,并且不需要通过操作系统的通常上下文切换来交换CPU,直到它完成为止。以防您不知道:因为CPU一次只能做一件事,操作系统会在小的时间片里将CPU的访问权转到所有运行的进程,从而产生多任务处理的错觉。CPU调度程序可以(并且确实)在执行过程中的任意一点中断进程——即使是在mid函数调用中。因此,对于像更新共享计数器变量这样的操作,两个进程可以同时尝试更新变量,它们必须以“原子”的方式执行,即。在任何其他进程可以被交换到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.

因此,我猜在这个例子中原子意味着属性读取器方法不能被中断——实际上意味着,由于其他一些线程/调用/函数被交换到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.

因为原子变量不能被中断,所以它们在任何点上所包含的值都是(线程锁定)保证不会被破坏,尽管,确保这个线程锁使访问它们的速度变慢。另一方面,非原子变量并没有这样的保证,但确实提供了快速访问的特权。总之,当你知道你的变量不能同时被多个线程访问并加快速度时,就使用非原子的方法。

#8


60  

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. 原子/ /默认
  3. nonatomic
  4. 原子
  5. strong = retain // Default
  6. strong = retain // Default。
  7. weak = unsafe_unretained
  8. 弱= unsafe_unretained
  9. retain
  10. 保留
  11. assign // Default
  12. 分配/ /默认
  13. unsafe_unretained
  14. unsafe_unretained
  15. copy
  16. 复制
  17. readonly
  18. 只读的
  19. readwrite // Default
  20. 读写/ /默认

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

在iOS中变量属性或修饰符中,你可以找到以上所有的属性,这肯定会对你有所帮助。

  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.
    • 非垃圾收集环境中的原子访问器(即在使用retain/release/autorelease时)将使用锁来确保另一个线程不会干扰正确的设置/获取值。
    • 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.
    • nonatomic不是默认行为。我们需要在属性属性中添加nonatomic关键字。
    • 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;
    

#9


52  

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.

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

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.

在创建多线程应用程序时,请参阅苹果的Objective-C 2.0文档中的“性能和线程”部分,了解更多信息和其他注意事项。

#10


51  

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.

原子保证访问该属性将以原子方式执行。例如,它总是返回一个完全初始化的对象,在一个线程上的任何get/集合都必须在另一个线程访问它之前完成。

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.

缺点:在多线程情况下,可能会出现垃圾值。

#11


30  

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.

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

#12


14  

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 :

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

self.myProperty = value;

is thread safe.

是线程安全的。

[myArray addObject:@"Abc"] 

is NOT thread safe.

不是线程安全的。

#13


12  

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.

如果我使用@property(原子,保留)NSString *myString,则会看到堆栈溢出问题。

#14


11  

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.

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

Example with MRC of a property with an ivar _internal:

以ivar _internal的属性的MRC为例:

[_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.

另一方面,nonatomic对您的代码没有添加任何内容。因此,如果您自己编写安全机制,那么它就是线程安全的。

@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!

不要忘记,这并不意味着整个属性是线程安全的。只有setter/getter的方法调用是。但是如果您使用setter和在同一时间使用两个不同线程的getter,它也可能被破坏!

#15


9  

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.

另一方面,非原子的,正如你们可能猜到的,只是意味着,“不要做那些原子的东西。“你失去的是保证你总能得到一些东西。”如果你试着在写的中间读,你可以得到垃圾数据。但是,另一方面,你走得快一点。因为原子属性需要做一些魔术来保证你会得到一个值,它们会稍微慢一点。如果这是一个您正在访问的属性,那么您可能想要下到nonatomic,以确保您不会产生这样的速度惩罚。

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

在这里看到更多:https://realm.io/news/tmi-objective-c-property-attributes/

#16


8  

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.

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

#17


8  

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

如果你从线程A调用“name”,

And

At the same time if you call

如果你打电话的话。

[self setName:@"Datta"]

from thread B,

从线程B,

Now If *name property is nonatomic then

现在,如果*name属性是非原子的。

  • It will return value "Datta" for A
  • 它将返回值“Datta”为A。
  • It will return value "Datta" for B
  • 它将为B返回值“Datta”。

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

如果*name属性是原子的。

  • It will ensure value "Sourov" for A
  • 它将确保“Sourov”的价值。
  • Then It will return value "Datta" for B
  • 然后它将返回值“Datta”为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.

-Nonatomic不是默认行为,我们需要在属性属性中添加nonatomic关键字。

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.

因为在Swift的确认中,Swift属性在ObjC意义上是非原子的。原因之一是,您会考虑是否每个属性的原子性足以满足您的需求。

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

参考: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

更多信息请访问http://rdcworld- iphone.blogspot.in/2012/12/variableproperty attributes-or.html。

#18


7  

Before discussing about the attributes of @property, you should know what is the use of @property. @property offers a way to define the information that a class is intended to encapsulate. If you declare an object/variable using @property, then that object/variable will be accessible to other classes importing its class. If you declare an object using @property in the header file, then you have to synthesize it using @synthesize in the implementation file.

在讨论@property的属性之前,您应该知道@property的用途是什么。@property提供了一种方法来定义类要封装的信息。如果您使用@property声明一个对象/变量,那么该对象/变量将被其他导入其类的类访问。如果在头文件中使用@property声明一个对象,那么必须在实现文件中使用@synthesize合成它。

Example:

例子:

.h class

. h类

@interface ExampleClass : NSObject
   @property (nonatomic, retain) NSString *name;
@end

.m class

m类

@implementation ExampleClass
   @synthesize name;
@end

Now the compiler will synthesize accessor methods for name.

现在,编译器将为名称合成访问器方法。

ExampleClass *newObject=[[ExampleClass alloc]init];
NSString *name1=[newObject name]; // get 'name'
[obj setName:@“Tiger”];

List of attributes of @property : atomic. nonatomic. retain. copy. readonly. readwrite. assign. strong.

@property的属性列表:原子。原子。保留。副本。只读的。读写。分配。强。

atomic : It is the default behaviour. If an object is declared as atomic then it becomes thread-safe. Thread-safe means, at a time only one thread of a particular instance of that class can have the control over that object.

原子:它是默认行为。如果一个对象被声明为原子,那么它就会变成线程安全的。线程安全的意思是,在某个时候,该类的某个特定实例的一个线程可以对该对象进行控制。

Example :

例子:

@property NSString *name; //by default atomic
@property (atomic)NSString *name; // explicitly declared atomic

nonatomic: It is not thread-safe. You can use the nonatomic property attribute to specify 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. For this reason, it’s faster to access a nonatomic property than an atomic one. @property (nonatomic)NSString *name;

nonatomic:它不是线程安全的。您可以使用nonatomic property属性来指定合成的访问器直接设置或返回一个值,如果相同的值从不同的线程同时访问,则不保证会发生什么。因此,访问非原子属性比访问原子属性更快。@ property(原子)NSString *名称;

retain: is required when the attribute is a pointer to an object.The setter method will increase retain count of the object, so that it will occupy memory in autorelease pool. @property (retain)NSString *name;

retain:当属性是指向对象的指针时,就需要保留。setter方法将增加对象的保留计数,以便它将占用autorelease池中的内存。@ property(保留)NSString *名称;

copy: If you use copy, you can't use retain. Using copy instance of the class will contain its own copy. Even if a mutable string is set and subsequently changed, the instance captures whatever value it has at the time it is set. No setter and getter methods will be synthesized.

复制:如果你使用复制,你不能使用保留。使用类的复制实例将包含它自己的副本。即使一个可变字符串被设置并且随后发生了更改,该实例也捕获了它在设置时所拥有的任何值。没有一个setter和getter方法会被合成。

@property (copy) NSString *name;

NSMutableString *nameString = [NSMutableString stringWithString:@"Liza"];    
xyzObj.name = nameString;    
[nameString appendString:@"Pizza"];

readonly: If you don't want to allow the property to be changed via setter method, you can declare the property readonly. @property (readonly) NSString *name;

readonly:如果您不想允许通过setter方法更改属性,则可以声明属性readonly。@ property(只读的)NSString *名称;

readwrite: is the default behaviour. You don't need to specify readwrite attribute explicitly.

readwrite:默认行为。您不需要显式指定readwrite属性。

@property (readwrite) NSString *name;

@ property(读写)NSString *名称;

assign: will generate a setter which assigns the value to the instance variable directly, rather than copying or retaining it. This is best for primitive types like NSInteger and CGFloat, or objects you don't directly own, such as delegates.

赋值:将生成一个setter,它直接将值分配给实例变量,而不是复制或保留它。对于像NSInteger和CGFloat这样的基本类型,或者您不直接拥有的对象,比如委托,这是最好的。

@property (assign) NSInteger year;

@ property(分配)NSInteger;

strong: is a replacement for retain. @property (nonatomic, strong) AVPlayer *player;

强:是保留的替代品。@property (nonatomic, strong) AVPlayer *player;

unsafe_unretained: There are a few classes in Cocoa and Cocoa Touch that don’t yet support weak references, which means you can’t declare a weak property or weak local variable to keep track of them. These classes include NSTextView, NSFont and NSColorSpace,etc. If you need to use a weak reference to one of these classes, you must use an unsafe reference. An unsafe reference is similar to a weak reference in that it doesn’t keep its related object alive, but it won’t be set to nil if the destination object is deallocated.

unsafe_un:在Cocoa和Cocoa Touch中有一些类不支持弱引用,这意味着您不能声明一个弱属性或弱本地变量来跟踪它们。这些类包括NSTextView、NSFont和NSColorSpace等。如果您需要对其中一个类使用弱引用,则必须使用不安全的引用。一个不安全的引用类似于弱引用,因为它不会将相关对象保存起来,但是如果目标对象是deallocation,它不会被设置为nil。

@property (unsafe_unretained) NSObject *unsafeProperty;

@ property(unsafe_unretained)NSObject * unsafeProperty;

#19


7  

Before you begin: You must know that every object in memory needs to be deallocated from memory for a new write 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.

在开始之前:您必须知道内存中的每个对象都需要从内存中释放,以便进行新的写入操作。你不能只是简单地写在纸上。你必须先擦除(dealloc)它,然后你可以写在它上面。如果在擦除的时候(或完成了一半),还没有写过(或写了一半),你试着去读它,可能会有很大的问题!原子和非原子帮助您以不同的方式处理这个问题。

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

先读这个问题,然后读Bbum的答案。此外,阅读我的摘要。


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 wrote 4 of the 8 letters to written, 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.
  • 如果一个人想写,只写4 8字母写的,中间没有可以阅读,阅读只能当所有8个字母写- - >没有读(得到)将发生在一个线程仍然是写作,即如果有8个字节字节写,只写4个字节,那一刻,你是不允许读。但是,既然我说它不会崩溃,那么它就会从一个自动的对象的值中读取。
  • 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 dealloced to write, you would could either get value from the final fully written value by ThreadB or get something from autorelease pool.
  • 如果在写之前,你已经把之前写在纸上的东西擦掉了,然后有人想读,你仍然可以阅读。如何?你会读到类似Mac OS垃圾桶的东西(因为垃圾桶还没有被100%清除……)如果ThreadA是用来读取的,而ThreadB已经处理好了,那么你可以通过ThreadB获得最终的完整的值,或者从autorelease池中得到一些东西。

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.

保留计数是在Objective-C中管理内存的方式。当您创建一个对象时,它的retain count为1。当您发送一个对象一个retain消息时,它的retain count将增加1。当您向一个对象发送一个发布消息时,它的保留计数将减少1。当您发送一个对象为autorelease消息时,它的保留计数在将来某个阶段将被减少1。如果一个对象的retain count被还原为0,那么它就是deallocation。

  • Atomic doesn't guarantee thread safety, though its 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.
  • 原子并不保证线程安全,尽管它对实现线程安全很有用。线程安全相对于您如何编写代码/您正在读/写的线程队列。它只保证非crashable的多线程。

Wait 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, because 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 you 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 wrote) --> Doesn't guarantee to not crash, because it doesn't use autorelease mechanism.
  • 因为没有这样的东西像Mac OS垃圾桶,那么没人会在乎你是否总是一个值(<——这可能导致崩盘),也没有任何人关心如果中途有人试图读你写(尽管一半写在内存中非常不同于一半写在纸上,记忆可以从之前给你一个疯狂愚蠢的价值,而在纸上你只能看到一半的写)- - >并不能保证不会崩溃,因为它不使用生成机制。
  • 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 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.

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

#20


4  

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

原子属性确保保留一个完全初始化的值,不管有多少线程在执行getter和setter。

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.

非原子属性指定了合成的访问器简单地设置或返回一个值,如果相同的值从不同的线程同时访问,则不保证会发生什么。

#21


3  

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.

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

#22


2  

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.

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

#23


0  

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

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

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

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

#24


0  

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 provide the mutex lock.Now it serve 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

为了简化整个混乱,让我们理解互斥锁。互斥锁的名称锁定了对象的可变性。因此,如果对象被一个类访问,其他类都不能访问相同的对象。在iOS @sychronise中也提供互斥锁。现在它以FIFO模式运行,并确保流不会受到共享同一实例的两个类的影响。但是,如果任务在主线程上,则避免使用原子属性访问对象,因为它可能会占用您的UI并降低性能。

#25


0  

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

#26


0  

Let's take an example:-

让我们举一个例子:-

@property (atomic, strong) NSString *atomicProperty;
@property (nonatomic, strong) NSString *nonAtomicProperty;

Atomic Properties:-

原子的属性:

1) Defining a property as atomic will guarantee that a valid value will be returned. Notice that valid does not always mean correct (more on that in the next section of this post)

1)将属性定义为原子将保证返回一个有效值。请注意,有效并不总是意味着正确(在本文的下一节将对此进行详细说明)

2) Atomic properties suffer from the minor performance hit due to locking and unlocking before and after setting/getting a value.

2)原子性能受限于在设置/获取值之前和之后锁定和解锁所造成的轻微性能损失。

3) Atomic is the default behavior for properties — this is what you get if you don’t specify anything.

3)原子是属性的默认行为——如果你没有指定任何东西,这就是你得到的结果。

Non-Atomic Properties:-

非原子的属性:

1) Nonatomic properties have no guarantee regarding the returned value.

1)非原子属性对返回值没有保证。

2) It can be the correct value, a partially written value or even some garbage value.

它可以是正确的值,部分写入值,甚至是一些垃圾值。

3) As most things that are not safe — this comes with an enhanced speed of accessing these properties.

3)由于大多数不安全的东西,这带来了访问这些属性的速度。

Let's see how does the Objective-C runtime do this programmatically?

让我们看看Objective-C运行时如何以编程的方式进行操作?

Let’s look at the “set value” method for the Objective-C runtime.

让我们来看看Objective-C运行时的“set value”方法。

Notice how nonatomic properties are directly setting the value of the property while an atomic property is using locks to protect the set operation

注意非原子属性如何直接设置属性的值,而原子属性使用锁来保护集合操作。

原子和非原子属性的区别是什么?

#1


1652  

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).

最后两个是相同的;“原子”是默认行为(请注意,它实际上不是关键字;它只在没有非原子的情况下指定——在最近版本的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).

假设您是@ synzing方法实现,原子vs非原子更改生成的代码。如果您正在编写自己的setter/getter,那么原子/非原子/保留/分配/复制仅仅是一个建议。(注意:@synthesize现在是LLVM最新版本的默认行为。也不需要声明实例变量;它们也会被自动合成,并且会有一个前缀以防止意外的直接访问。

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.

使用“原子”,合成的setter/getter将确保所有值始终从getter中返回,或者由setter设置,而不考虑任何其他线程上的setter活动。也就是说,如果线程A位于getter的中间,而线程B调用setter,那么一个实际可行的值——很可能是一个autoreleatedobject——将会返回给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.

“原子”不做的是对线程安全做任何保证。如果线程与线程同时调用getter B和C调用setter与不同价值观,线程A可能会返回的三个值中的任何一个,前一个被调用setter或者值传递到setter的B和C .同样,价值的对象可能会从B或C,无法告诉。

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.

在这种情况下,线程A可以通过调用setFirstName来重命名对象:然后调用setLastName:。与此同时,线程B可能在线程A的两个调用之间调用fullName,并将接收新名称和旧名称。

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.

要解决这个问题,您需要一个事务模型。也就是一些其他类型的同步和/或排除,允许一个人在依赖属性被更新时不允许访问fullName。

#2


340  

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.

这是在苹果的文档中解释的,但下面是一些实际发生的例子。注意,没有“原子”关键字,如果您没有指定“nonatomic”,那么属性是原子的,但是显式地指定“原子”将导致错误。

//@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.

基本上,原子版本必须采取一个锁来保证线程安全,也是撞裁判依靠对象(和autorelease数到平衡),对象是保证调用者的存在,否则如果另一个线程是一个潜在的竞态条件设置值,导致裁判数降至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.

实际上,根据属性是标量值还是对象,以及如何保持、复制、只读、非原子等交互,有很多不同的变体。一般来说,属性合成器只知道如何为所有组合做“正确的事情”。

#3


146  

Atomic

  • is the default behavior
  • 是默认行为
  • will ensure the present process is completed by the CPU, before another process accesses the variable
  • 将确保当前进程由CPU完成,然后另一个进程访问该变量?
  • 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)
  • 更快(对于合成的代码,即使用@property和@synthesize创建的变量)
  • not thread-safe
  • 非线程安全
  • may result in unexpected behavior, when two different process access the same variable at the same time
  • 当两个不同的进程同时访问同一个变量时,可能会导致意外的行为?

#4


123  

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.

假设有一个原子字符串属性称为“名称”,如果你叫(自我setName:@“A”)从线程,叫(自我setName:@“B”)从线程B,C并从线程调用(自己的名字),然后所有操作在不同的线程将执行连续这意味着如果一个线程正在执行一个setter和getter,那么其他线程会等待。

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.

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

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.

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

#5


108  

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.

我一直认为原子是一种默认,很奇怪。在抽象级别上,我们使用一个类的原子属性作为实现100%线程安全的工具。对于真正正确的多线程程序,程序员的干预几乎是必需的。与此同时,性能特征和执行还没有详细的深入。多年来,我编写了一些非常多线程的程序,我一直在声明我的属性是非原子性的,因为原子对任何目的都不敏感。在讨论原子和非原子属性的细节时,我做了一些分析,遇到了一些奇怪的结果。

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).

好的。首先我要澄清的是,锁定实现是实现定义和抽象的。路易斯在他的例子中使用@synchronized(self)——我把这看作是一个常见的混乱来源。实现并不实际使用@synchronized(self);它使用对象级旋转锁。Louis的插图对于使用我们都熟悉的构造来说是很好的,但是重要的是知道它不使用@synchronized(self)。

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

另一个区别是,原子属性将在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.

这里有一个有趣的部分:在一些情况下,在无争用(例如单线程)情况下使用原子属性访问的性能可能非常快。在不太理想的情况下,使用原子访问的开销可能超过非原子访问开销的20倍。在有争议的情况下,使用7个线程的3字节结构(2.2 GHz Core i7 Quad Core, x86_64)的速度要慢44倍。三字节结构是一个非常慢的属性的例子。

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.

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

Objects in contested cases can also exceed 50 times.

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

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.

由于实现的优化和变化,在这些上下文中测量实际的影响是相当困难的。你可能经常听到类似“相信它,除非你个人资料,发现它是一个问题”之类的东西。由于抽象级别,实际上很难测量实际的影响。从概要文件中收集实际成本可能非常耗时,而且由于抽象,非常不准确。同样,ARC和MRC可以产生很大的不同。

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

因此,让我们回过头来,不关注属性访问的实现,我们将包括像objc_msgSend这样的常见疑点,并检查一些在无争议的情况下对NSString getter的许多调用的实际高级结果(以秒为单位):

  • MRC | nonatomic | manually implemented getters: 2
  • MRC |非原子|手动执行getters: 2。
  • MRC | nonatomic | synthesized getter: 7
  • MRC |非原子|合成的吸气剂:7。
  • MRC | atomic | synthesized getter: 47
  • MRC |原子|合成吸气剂:47。
  • ARC | nonatomic | synthesized getter: 38 (note: ARC's adding ref count cycling here)
  • |非原子|合成的getter: 38(注:ARC在这里添加ref count循环)
  • ARC | atomic | synthesized getter: 47
  • ARC |原子|合成吸气剂: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.

虽然我关注性能,但我还是先说语义!与此同时,对于许多项目来说,性能是一个低优先级。然而,了解执行细节和使用的技术成本当然不会有坏处。您应该使用正确的技术来满足您的需求、目的和能力。希望这会为您节省几个小时的比较,并帮助您在设计程序时做出更明智的决定。

#6


88  

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 .

不像nonatomic那样快,因为nonatomic在运行时不需要任何监视程序。

Where to use nonatomic:

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

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

#7


67  

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.

“原子”意味着它不能被分解。在OS/编程术语中,一个原子函数调用是一个不能被中断的函数——必须执行整个函数,并且不需要通过操作系统的通常上下文切换来交换CPU,直到它完成为止。以防您不知道:因为CPU一次只能做一件事,操作系统会在小的时间片里将CPU的访问权转到所有运行的进程,从而产生多任务处理的错觉。CPU调度程序可以(并且确实)在执行过程中的任意一点中断进程——即使是在mid函数调用中。因此,对于像更新共享计数器变量这样的操作,两个进程可以同时尝试更新变量,它们必须以“原子”的方式执行,即。在任何其他进程可以被交换到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.

因此,我猜在这个例子中原子意味着属性读取器方法不能被中断——实际上意味着,由于其他一些线程/调用/函数被交换到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.

因为原子变量不能被中断,所以它们在任何点上所包含的值都是(线程锁定)保证不会被破坏,尽管,确保这个线程锁使访问它们的速度变慢。另一方面,非原子变量并没有这样的保证,但确实提供了快速访问的特权。总之,当你知道你的变量不能同时被多个线程访问并加快速度时,就使用非原子的方法。

#8


60  

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. 原子/ /默认
  3. nonatomic
  4. 原子
  5. strong = retain // Default
  6. strong = retain // Default。
  7. weak = unsafe_unretained
  8. 弱= unsafe_unretained
  9. retain
  10. 保留
  11. assign // Default
  12. 分配/ /默认
  13. unsafe_unretained
  14. unsafe_unretained
  15. copy
  16. 复制
  17. readonly
  18. 只读的
  19. readwrite // Default
  20. 读写/ /默认

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

在iOS中变量属性或修饰符中,你可以找到以上所有的属性,这肯定会对你有所帮助。

  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.
    • 非垃圾收集环境中的原子访问器(即在使用retain/release/autorelease时)将使用锁来确保另一个线程不会干扰正确的设置/获取值。
    • 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.
    • nonatomic不是默认行为。我们需要在属性属性中添加nonatomic关键字。
    • 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;
    

#9


52  

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.

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

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.

在创建多线程应用程序时,请参阅苹果的Objective-C 2.0文档中的“性能和线程”部分,了解更多信息和其他注意事项。

#10


51  

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.

原子保证访问该属性将以原子方式执行。例如,它总是返回一个完全初始化的对象,在一个线程上的任何get/集合都必须在另一个线程访问它之前完成。

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.

缺点:在多线程情况下,可能会出现垃圾值。

#11


30  

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.

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

#12


14  

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 :

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

self.myProperty = value;

is thread safe.

是线程安全的。

[myArray addObject:@"Abc"] 

is NOT thread safe.

不是线程安全的。

#13


12  

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.

如果我使用@property(原子,保留)NSString *myString,则会看到堆栈溢出问题。

#14


11  

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.

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

Example with MRC of a property with an ivar _internal:

以ivar _internal的属性的MRC为例:

[_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.

另一方面,nonatomic对您的代码没有添加任何内容。因此,如果您自己编写安全机制,那么它就是线程安全的。

@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!

不要忘记,这并不意味着整个属性是线程安全的。只有setter/getter的方法调用是。但是如果您使用setter和在同一时间使用两个不同线程的getter,它也可能被破坏!

#15


9  

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.

另一方面,非原子的,正如你们可能猜到的,只是意味着,“不要做那些原子的东西。“你失去的是保证你总能得到一些东西。”如果你试着在写的中间读,你可以得到垃圾数据。但是,另一方面,你走得快一点。因为原子属性需要做一些魔术来保证你会得到一个值,它们会稍微慢一点。如果这是一个您正在访问的属性,那么您可能想要下到nonatomic,以确保您不会产生这样的速度惩罚。

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

在这里看到更多:https://realm.io/news/tmi-objective-c-property-attributes/

#16


8  

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.

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

#17


8  

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

如果你从线程A调用“name”,

And

At the same time if you call

如果你打电话的话。

[self setName:@"Datta"]

from thread B,

从线程B,

Now If *name property is nonatomic then

现在,如果*name属性是非原子的。

  • It will return value "Datta" for A
  • 它将返回值“Datta”为A。
  • It will return value "Datta" for B
  • 它将为B返回值“Datta”。

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

如果*name属性是原子的。

  • It will ensure value "Sourov" for A
  • 它将确保“Sourov”的价值。
  • Then It will return value "Datta" for B
  • 然后它将返回值“Datta”为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.

-Nonatomic不是默认行为,我们需要在属性属性中添加nonatomic关键字。

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.

因为在Swift的确认中,Swift属性在ObjC意义上是非原子的。原因之一是,您会考虑是否每个属性的原子性足以满足您的需求。

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

参考: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

更多信息请访问http://rdcworld- iphone.blogspot.in/2012/12/variableproperty attributes-or.html。

#18


7  

Before discussing about the attributes of @property, you should know what is the use of @property. @property offers a way to define the information that a class is intended to encapsulate. If you declare an object/variable using @property, then that object/variable will be accessible to other classes importing its class. If you declare an object using @property in the header file, then you have to synthesize it using @synthesize in the implementation file.

在讨论@property的属性之前,您应该知道@property的用途是什么。@property提供了一种方法来定义类要封装的信息。如果您使用@property声明一个对象/变量,那么该对象/变量将被其他导入其类的类访问。如果在头文件中使用@property声明一个对象,那么必须在实现文件中使用@synthesize合成它。

Example:

例子:

.h class

. h类

@interface ExampleClass : NSObject
   @property (nonatomic, retain) NSString *name;
@end

.m class

m类

@implementation ExampleClass
   @synthesize name;
@end

Now the compiler will synthesize accessor methods for name.

现在,编译器将为名称合成访问器方法。

ExampleClass *newObject=[[ExampleClass alloc]init];
NSString *name1=[newObject name]; // get 'name'
[obj setName:@“Tiger”];

List of attributes of @property : atomic. nonatomic. retain. copy. readonly. readwrite. assign. strong.

@property的属性列表:原子。原子。保留。副本。只读的。读写。分配。强。

atomic : It is the default behaviour. If an object is declared as atomic then it becomes thread-safe. Thread-safe means, at a time only one thread of a particular instance of that class can have the control over that object.

原子:它是默认行为。如果一个对象被声明为原子,那么它就会变成线程安全的。线程安全的意思是,在某个时候,该类的某个特定实例的一个线程可以对该对象进行控制。

Example :

例子:

@property NSString *name; //by default atomic
@property (atomic)NSString *name; // explicitly declared atomic

nonatomic: It is not thread-safe. You can use the nonatomic property attribute to specify 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. For this reason, it’s faster to access a nonatomic property than an atomic one. @property (nonatomic)NSString *name;

nonatomic:它不是线程安全的。您可以使用nonatomic property属性来指定合成的访问器直接设置或返回一个值,如果相同的值从不同的线程同时访问,则不保证会发生什么。因此,访问非原子属性比访问原子属性更快。@ property(原子)NSString *名称;

retain: is required when the attribute is a pointer to an object.The setter method will increase retain count of the object, so that it will occupy memory in autorelease pool. @property (retain)NSString *name;

retain:当属性是指向对象的指针时,就需要保留。setter方法将增加对象的保留计数,以便它将占用autorelease池中的内存。@ property(保留)NSString *名称;

copy: If you use copy, you can't use retain. Using copy instance of the class will contain its own copy. Even if a mutable string is set and subsequently changed, the instance captures whatever value it has at the time it is set. No setter and getter methods will be synthesized.

复制:如果你使用复制,你不能使用保留。使用类的复制实例将包含它自己的副本。即使一个可变字符串被设置并且随后发生了更改,该实例也捕获了它在设置时所拥有的任何值。没有一个setter和getter方法会被合成。

@property (copy) NSString *name;

NSMutableString *nameString = [NSMutableString stringWithString:@"Liza"];    
xyzObj.name = nameString;    
[nameString appendString:@"Pizza"];

readonly: If you don't want to allow the property to be changed via setter method, you can declare the property readonly. @property (readonly) NSString *name;

readonly:如果您不想允许通过setter方法更改属性,则可以声明属性readonly。@ property(只读的)NSString *名称;

readwrite: is the default behaviour. You don't need to specify readwrite attribute explicitly.

readwrite:默认行为。您不需要显式指定readwrite属性。

@property (readwrite) NSString *name;

@ property(读写)NSString *名称;

assign: will generate a setter which assigns the value to the instance variable directly, rather than copying or retaining it. This is best for primitive types like NSInteger and CGFloat, or objects you don't directly own, such as delegates.

赋值:将生成一个setter,它直接将值分配给实例变量,而不是复制或保留它。对于像NSInteger和CGFloat这样的基本类型,或者您不直接拥有的对象,比如委托,这是最好的。

@property (assign) NSInteger year;

@ property(分配)NSInteger;

strong: is a replacement for retain. @property (nonatomic, strong) AVPlayer *player;

强:是保留的替代品。@property (nonatomic, strong) AVPlayer *player;

unsafe_unretained: There are a few classes in Cocoa and Cocoa Touch that don’t yet support weak references, which means you can’t declare a weak property or weak local variable to keep track of them. These classes include NSTextView, NSFont and NSColorSpace,etc. If you need to use a weak reference to one of these classes, you must use an unsafe reference. An unsafe reference is similar to a weak reference in that it doesn’t keep its related object alive, but it won’t be set to nil if the destination object is deallocated.

unsafe_un:在Cocoa和Cocoa Touch中有一些类不支持弱引用,这意味着您不能声明一个弱属性或弱本地变量来跟踪它们。这些类包括NSTextView、NSFont和NSColorSpace等。如果您需要对其中一个类使用弱引用,则必须使用不安全的引用。一个不安全的引用类似于弱引用,因为它不会将相关对象保存起来,但是如果目标对象是deallocation,它不会被设置为nil。

@property (unsafe_unretained) NSObject *unsafeProperty;

@ property(unsafe_unretained)NSObject * unsafeProperty;

#19


7  

Before you begin: You must know that every object in memory needs to be deallocated from memory for a new write 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.

在开始之前:您必须知道内存中的每个对象都需要从内存中释放,以便进行新的写入操作。你不能只是简单地写在纸上。你必须先擦除(dealloc)它,然后你可以写在它上面。如果在擦除的时候(或完成了一半),还没有写过(或写了一半),你试着去读它,可能会有很大的问题!原子和非原子帮助您以不同的方式处理这个问题。

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

先读这个问题,然后读Bbum的答案。此外,阅读我的摘要。


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 wrote 4 of the 8 letters to written, 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.
  • 如果一个人想写,只写4 8字母写的,中间没有可以阅读,阅读只能当所有8个字母写- - >没有读(得到)将发生在一个线程仍然是写作,即如果有8个字节字节写,只写4个字节,那一刻,你是不允许读。但是,既然我说它不会崩溃,那么它就会从一个自动的对象的值中读取。
  • 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 dealloced to write, you would could either get value from the final fully written value by ThreadB or get something from autorelease pool.
  • 如果在写之前,你已经把之前写在纸上的东西擦掉了,然后有人想读,你仍然可以阅读。如何?你会读到类似Mac OS垃圾桶的东西(因为垃圾桶还没有被100%清除……)如果ThreadA是用来读取的,而ThreadB已经处理好了,那么你可以通过ThreadB获得最终的完整的值,或者从autorelease池中得到一些东西。

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.

保留计数是在Objective-C中管理内存的方式。当您创建一个对象时,它的retain count为1。当您发送一个对象一个retain消息时,它的retain count将增加1。当您向一个对象发送一个发布消息时,它的保留计数将减少1。当您发送一个对象为autorelease消息时,它的保留计数在将来某个阶段将被减少1。如果一个对象的retain count被还原为0,那么它就是deallocation。

  • Atomic doesn't guarantee thread safety, though its 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.
  • 原子并不保证线程安全,尽管它对实现线程安全很有用。线程安全相对于您如何编写代码/您正在读/写的线程队列。它只保证非crashable的多线程。

Wait 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, because 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 you 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 wrote) --> Doesn't guarantee to not crash, because it doesn't use autorelease mechanism.
  • 因为没有这样的东西像Mac OS垃圾桶,那么没人会在乎你是否总是一个值(<——这可能导致崩盘),也没有任何人关心如果中途有人试图读你写(尽管一半写在内存中非常不同于一半写在纸上,记忆可以从之前给你一个疯狂愚蠢的价值,而在纸上你只能看到一半的写)- - >并不能保证不会崩溃,因为它不使用生成机制。
  • 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 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.

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

#20


4  

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

原子属性确保保留一个完全初始化的值,不管有多少线程在执行getter和setter。

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.

非原子属性指定了合成的访问器简单地设置或返回一个值,如果相同的值从不同的线程同时访问,则不保证会发生什么。

#21


3  

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.

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

#22


2  

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.

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

#23


0  

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

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

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

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

#24


0  

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 provide the mutex lock.Now it serve 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

为了简化整个混乱,让我们理解互斥锁。互斥锁的名称锁定了对象的可变性。因此,如果对象被一个类访问,其他类都不能访问相同的对象。在iOS @sychronise中也提供互斥锁。现在它以FIFO模式运行,并确保流不会受到共享同一实例的两个类的影响。但是,如果任务在主线程上,则避免使用原子属性访问对象,因为它可能会占用您的UI并降低性能。

#25


0  

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

#26


0  

Let's take an example:-

让我们举一个例子:-

@property (atomic, strong) NSString *atomicProperty;
@property (nonatomic, strong) NSString *nonAtomicProperty;

Atomic Properties:-

原子的属性:

1) Defining a property as atomic will guarantee that a valid value will be returned. Notice that valid does not always mean correct (more on that in the next section of this post)

1)将属性定义为原子将保证返回一个有效值。请注意,有效并不总是意味着正确(在本文的下一节将对此进行详细说明)

2) Atomic properties suffer from the minor performance hit due to locking and unlocking before and after setting/getting a value.

2)原子性能受限于在设置/获取值之前和之后锁定和解锁所造成的轻微性能损失。

3) Atomic is the default behavior for properties — this is what you get if you don’t specify anything.

3)原子是属性的默认行为——如果你没有指定任何东西,这就是你得到的结果。

Non-Atomic Properties:-

非原子的属性:

1) Nonatomic properties have no guarantee regarding the returned value.

1)非原子属性对返回值没有保证。

2) It can be the correct value, a partially written value or even some garbage value.

它可以是正确的值,部分写入值,甚至是一些垃圾值。

3) As most things that are not safe — this comes with an enhanced speed of accessing these properties.

3)由于大多数不安全的东西,这带来了访问这些属性的速度。

Let's see how does the Objective-C runtime do this programmatically?

让我们看看Objective-C运行时如何以编程的方式进行操作?

Let’s look at the “set value” method for the Objective-C runtime.

让我们来看看Objective-C运行时的“set value”方法。

Notice how nonatomic properties are directly setting the value of the property while an atomic property is using locks to protect the set operation

注意非原子属性如何直接设置属性的值,而原子属性使用锁来保护集合操作。

原子和非原子属性的区别是什么?