关于iOS:atomic 属性和nonatomic属性有什么区别?

What's the difference between the atomic and nonatomic attributes?

在财产申报中,atomicnonatomic是什么意思?

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

这三者之间的操作区别是什么?


最后两个是相同的;"原子"是默认行为(请注意,它实际上不是关键字;它仅由缺少nonatomic->strike>——atomic在最新版本的llvm/clang中作为关键字添加而指定)。

假设您正在@synthesis方法实现,原子与非原子将更改生成的代码。如果您正在编写自己的setter/getter,那么atomic/nonatomic/retain/assign/copy只是建议性的。(注意:@synthesis现在是LLVM最新版本中的默认行为。也不需要声明实例变量;它们也将被自动合成,并在其名称前面加一个_,以防止意外的直接访问)。

使用"原子",合成的setter/getter将确保始终从getter返回一个完整的值或由setter设置,而不管其他线程上的setter活动如何。也就是说,如果线程A在getter的中间,而线程B调用setter,则实际可行的值(很可能是自动释放的对象)将返回到a中的调用者。

nonatomic中,没有这样的保证。因此,nonatomic比"原子"快得多。

"原子"不做的是保证线程安全。如果线程A同时调用getter,而线程B和C调用具有不同值的setter,则线程A可能会得到返回的三个值中的任意一个,即在调用任何setter之前返回的值,或者在B和C中传递给setter的值中的任意一个值。同样,对象也可能以B或C中的值结束,无法分辨。

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

添加到这一点:

单个属性的atomicity也不能保证多个依赖属性发挥作用时的线程安全。

考虑:

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

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

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


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

1
2
3
4
5
6
7
8
9
10
11
12
//@property(nonatomic, retain) UITextField *userName;
//Generates roughly

- (UITextField *) userName {
    return userName;
}

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

现在,原子变体有点复杂:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//@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。

根据属性是标量值还是对象,以及retain、copy、readonly、nonatomic等的交互方式,实际上这些内容的工作方式有很多不同的变体。一般来说,财产合成器只知道如何为所有组合做"正确的事情"。


原子的

  • 是默认行为
  • 在另一个进程访问变量之前,将确保当前进程由CPU完成
  • 不是很快,因为它可以确保整个过程完成

非原子的

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


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

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

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

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


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

What is the functional difference between these 3?

我一直把原子视为默认值,这很奇怪。在抽象级别,我们将类的原子属性用作实现100%线程安全的工具,这是一个很好的例子。对于真正正确的多线程程序,程序员的干预几乎是必然的要求。同时,性能特征和执行还没有详细介绍。这些年来,我编写了一些大量的多线程程序,一直以来我都把自己的属性声明为nonatomic,因为atomic对于任何目的都是不明智的。在讨论这个问题的原子和非原子性质的细节时,我做了一些分析,遇到了一些奇怪的结果。

执行

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

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

性能

这里有一个有趣的部分:在未经测试(例如单线程)的情况下,使用原子属性访问的性能在某些情况下可能非常快。在不太理想的情况下,使用原子访问的开销可能是nonatomic开销的20倍以上。对于三字节结构(2.2 GHz内核i7四核,x86_),使用7个线程的争用情况慢了44倍。三字节结构是一个非常慢的属性的例子。

有趣的一点是:三字节结构的用户定义的访问器比合成的原子访问器快52倍,比合成的非原子访问器快84%。

在有争议的情况下,对象也可以超过50倍。

由于优化的数量和实现中的变化,很难衡量这些环境中的实际影响。你可能经常听到这样的话:"相信它,除非你的资料和发现它是一个问题"。由于抽象级别的原因,实际上很难度量实际影响。从配置文件中收集实际成本可能非常耗时,而且由于抽象,因此非常不准确。同样,ARC和MRC也会有很大的不同。

因此,让我们后退一步,不要把重点放在属性访问的实现上,我们将包括像objc_msgSend这样的常见嫌疑人,并在未测试的情况下(以秒为单位的值)检查对NSStringgetter的许多调用的一些实际高级结果:

  • MRC非原子手动实现的getter:2
  • MRC非原子合成吸气剂:7
  • MRC原子合成吸气剂:47
  • 弧非原子合成吸气剂:38(注:弧在此处添加参考计数循环)
  • 弧原子合成吸气剂:47

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

虽然我非常关注性能,但我还是先说语义!同时,对于许多项目来说,性能是一个低优先级的问题。但是,了解您所使用的技术的执行细节和成本肯定不会有什么影响。你应该为你的需要、目的和能力使用正确的技术。希望这样可以节省几个小时的比较时间,帮助您在设计程序时做出更明智的决策。


原子=线程安全

非原子=无线程安全

线程安全:

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

在我们的背景下:

如果线程更改了实例的值,则更改的值对所有线程都可用,并且一次只能有一个线程更改该值。

使用atomic的地方:

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

atomic的含义:

不像nonatomic快,因为nonatomic不需要运行时的任何看门狗工作。

使用nonatomic的地方:

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


我在这里找到了一个关于原子和非原子性质的很好的解释。以下是一些相关的文本:

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

由于atomic变量不能被中断,因此它们在任何点上所包含的值(thread lock)都保证不被中断,尽管如此,确保这个thread lock会使对它们的访问变慢。另一方面,non-atomic变量没有这样的保证,但提供了快速访问的奢侈。总而言之,当您知道多个线程不能同时访问您的变量时,使用non-atomic,并加快速度。


在阅读了如此多的文章、堆栈溢出文章并制作演示应用程序以检查变量属性属性之后,我决定将所有属性信息放在一起:

  • atomic//违约
  • nonatomic
  • strong = retain//违约
  • weak = unsafe_unretained
  • retain
  • assign//违约
  • unsafe_unretained
  • copy
  • readonly
  • readwrite//违约
  • 在IOS中的variable property attributes或modifiers一文中,您可以找到上述所有属性,这绝对会对您有所帮助。

  • atomic

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

    例子:

    1
    2
    3
        @property (retain) NSString *name;

        @synthesize name;
  • nonatomic

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

    例子:

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

        @synthesize name;

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

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

    有关创建多线程应用程序时的更多信息和其他注意事项,请参阅苹果公司目标C 2.0文档的"性能和线程"部分。


    Atomic:

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

    如果您想象下面的函数同时出现在两个线程上,那么您就可以看到为什么结果不漂亮了。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    -(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;
      }

      ...
    }

    赞成的意见:每次返回完全初始化的对象都是多线程情况下的最佳选择。

    欺骗:性能下降,执行速度变慢

    Non Atomic:

    与原子不同,它不能确保每次都返回完全初始化的对象。

    赞成的意见:执行速度极快。

    欺骗:多线程情况下垃圾值的可能性。


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

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


    Atomic是线程安全的,它很慢,它很好地保证(不保证)无论有多少线程试图访问同一区域,都只提供锁定的值。使用Atomic时,在该函数中编写的一段代码将成为关键部分的一部分,一次只能执行一个线程。

    它只保证螺纹的安全;它不能保证。我的意思是你雇了一个专业的司机来开你的车,但这并不能保证车不会出事故。然而,可能性仍然很小。

    原子-它不能分解,所以结果是可以预料的。与非原子-当另一个线程访问内存区域时,它可以修改它,所以结果是意外的。

    代码对话:

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

    1
    self.myProperty = value;

    线程安全。

    1
    [myArray addObject:@"Abc"]

    不是线程安全的。


    没有这样的关键字"原子"

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

    我们可以用上面的

    1
    @property(retain) UITextField *userName;

    如果我使用@property(atomic,retain)nsstring*mystring,请参阅堆栈溢出问题。


    默认值是atomic,这意味着无论何时使用该属性都会导致性能损失,但它是线程安全的。Objective-C所做的是设置一个锁,因此只要执行setter/getter,只有实际的线程才能访问变量。

    带有内部ivar_属性的MRC示例:

    1
    2
    3
    4
    [_internal lock]; //lock
    id result = [[value retain] autorelease];
    [_internal unlock];
    return result;

    所以最后两个是相同的:

    1
    2
    3
    @property(atomic, retain) UITextField *userName;

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

    另一方面,nonatomic没有向代码中添加任何内容。因此,只有您自己编写安全机制,它才是线程安全的。

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

    关键字根本不必作为第一个属性写入。

    别忘了,这并不意味着整个属性是线程安全的。只有setter/getter的方法调用是。但是如果你使用一个setter,然后同时使用两个不同线程的getter,它也可能会被破坏!


    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.

    更多信息请参见:https://realm.io/news/tmi-objective-c-property-attributes/


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

    例子:

    H类

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

    M类

    1
    2
    3
    @implementation ExampleClass
       @synthesize name;
    @end

    现在编译器将为name合成访问器方法。

    1
    2
    3
    ExampleClass *newObject=[[ExampleClass alloc]init];
    NSString *name1=[newObject name]; // get 'name'
    [obj setName:@"Tiger"];

    @property属性列表:原子的非原子的保留。复制。只读。读写。指派。强壮。

    原子:它是默认行为。如果一个对象声明为原子对象,那么它就成为线程安全的。线程安全意味着,一次只有该类特定实例的一个线程可以控制该对象。

    例子:

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

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

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

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

    1
    2
    3
    4
    5
    @property (copy) NSString *name;

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

    只读:如果不希望通过setter方法更改属性,则可以将属性声明为只读。@property (readonly) NSString *name;

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

    @property (readwrite) NSString *name;

    assign:将生成一个setter,它将值直接分配给实例变量,而不是复制或保留它。这最适合于nsinteger和cgfloat之类的基本类型,或者不直接拥有的对象,例如委托。

    @property (assign) NSInteger year;

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

    不安全:cocoa和cocoa touch中有一些类还不支持弱引用,这意味着您不能声明弱属性或弱局部变量来跟踪它们。这些类包括nstextview、nsfont和nscollorspace等。如果需要使用对这些类之一的弱引用,则必须使用不安全的引用。不安全引用类似于弱引用,因为它不会使相关对象保持活动状态,但如果目标对象被释放,则不会将其设置为nil。

    @property (unsafe_unretained) NSObject *unsafeProperty;


    • -原子意味着只有一个线程访问变量(静态类型)。
    • -原子是线程安全的。
    • -但是它的性能很慢

    如何声明:

    因为原子是默认的,所以,

    1
    @property (retain) NSString *name;

    在实施文件中

    1
    self.name = @"sourov";

    假设与三个属性相关的任务是

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

    所有属性并行工作(如异步)。

    如果您从线程A调用"name",

    如果你打电话的话

    1
    [self setName:@"Datta"]

    从线程B,

    如果*name属性是非原子的,那么

    • 它将返回值"datta"
    • 它将返回b的值"datta"

    这就是为什么非原子被称为线程不安全,但由于并行执行,它的性能很快。

    现在,如果*名称属性是原子属性

    • 它将确保"sourov"的价值
    • 然后它将返回b的值"datta"

    这就是为什么原子被称为线程安全和这就是为什么它被称为读写安全的原因

    这种情况下的行动将连续进行。性能也很慢

    -非原子意味着多线程访问变量(动态类型)。

    -非原子是线程不安全的。

    -但是它的性能很快

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

    为了In Swift确认swift属性在objc意义上是非原子的。一个原因是,您需要考虑每个属性的原子性是否足以满足您的需求。

    参考:https://forums.developer.apple.com/thread/25642

    欲了解更多信息,请访问网站http://rdcworld-iphone.blogspot.in/2012/12/variable-property-attributes-or.html


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

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


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

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

    atomic将始终保证

    • 如果两个不同的人想同时读和写,你的论文就不会被烧毁!-->即使在竞争条件下,应用程序也不会崩溃。
    • 如果一个人试图写,但只写了8个字母中的4个,那么中间没有人可以读,只有在所有8个字母都写了之后,才能读。->在"一个仍在写的线程"上不会发生读(get),也就是说,如果有8个字节到字节要写,而只有4个字节要写--到那时为止,你应该不允许从中读取。但因为我说过它不会崩溃,所以它会从自动释放对象的值中读取。
    • 如果在写之前你已经删除了以前写在纸上的内容,然后有人想读,你仍然可以读。怎样?您将从类似于Mac OS垃圾箱的内容中读取(因为垃圾箱仍然没有100%被清除…它还处于空白状态)--->如果要在threada已被释放写入的情况下读取,您可以从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.

    • 原子不保证线程安全,尽管它对实现线程安全很有用。线程安全性与您如何编写代码/从哪个线程队列读取/写入代码有关。它只保证不崩溃的多线程。

    什么?!多线程和线程安全是否不同?

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

    nonatomic

    • 既然没有Mac OS垃圾箱这样的东西,那么没有人关心你是否总是得到一个值(<--这可能导致崩溃),也没有人关心是否有人试图在你的写作过程中读到一半(尽管在记忆中写一半与在纸上写一半非常不同,但在记忆中它可以给你一个疯狂的UPID值来自以前,而在纸上,您只能看到写的内容的一半)->不能保证不会崩溃,因为它不使用自动释放机制。
    • 不保证读取完整的写入值!
    • 比原子更快

    总的来说,它们在两个方面是不同的:

    • 是否因为有或没有自动释放池而崩溃。

    • 允许在"尚未完成写入或空值"的中间位置读取,或不允许且仅允许在值完全写入时读取。


    原子属性确保保留完全初始化的值,而不管有多少线程正在对其执行getter和setter操作。

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


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

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


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


    原子性原子(默认)P></

    如果原子is the default:*什么是原子型,你的财产。原子性质的移调that is an如果你试图从你读它,会得到有效的反馈值。它does not make any that might be about什么价值包,but You will not just get back好垃圾数据,存储。这是我给你的是,如果你allows多线程或多个过程变量(单指指点点,一个线程可以读取和写入另一个线程可以。如果他们打at the same time,the one is to get读者线程移调的值或者二:of the before the change or after the change。我给你任何原子does not sort of which is about of担保你会得到的那些值。是真的commonly原子被混淆与线程安全,那是不正确的。You need to your other方式保证线程安全。不管一个人多,原子会担保,如果你试着读,你回来some kind of value。P></

    完备P></

    在翻盖侧,非原子As You can guess,probably,只是"不给,均值,原子的东西。"是你失去is that担保你总是回来的东西。如果你试图读写在中间的垃圾,你可以回来的日期。但是,在其他的手,你走快一点。我要给你一些神奇的原子性质的担保价值,你会回来,他们是slower位。if it is a property是accessing很多,你想,你可以拖放到完备的措施让你incurring死刑,不是速度。接入P></

    HTTPS:/ / /礼貌/ WTL academy.realm.io posts -属性-性能- Objective-C /P></

    物业属性(原子和原子不完备)是茶叶中的对应reflected敏捷宣言的原子性质,but the implementation of the Objective-C包仍然保持accessed property is when the imported from斯威夫特。P></

    知道吗?-?如果你定义安物业在Objective-C中原子原子when used by恩仍会迅速。P></

    礼貌HTTPS:/ / / / medium.com @ yogevsitton原子与非原子属性--兼d11c23f4366c碰撞P></


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

    非原子:由于没有线程锁定机制,因此无法确保线程安全。


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

    互斥锁,根据名称,锁定对象的可变性。因此,如果对象被一个类访问,其他类就不能访问同一个对象。

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


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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
     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);
        }

    原子属性:当一个变量被赋予原子属性,这意味着它只有一个线程访问,并且它将是线程安全的,并且在性能方面也很好,那么它将具有默认行为。

    非原子属性:当分配了原子属性的变量意味着它具有多线程访问权限,并且它将不具有线程安全性,并且在性能方面速度较慢时,它将具有默认行为,并且当两个不同的线程希望同时访问变量时,它将给出意外的结果。