primefaces和非primefaces属性之间有什么区别?

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

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

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

最后两个是相同的; “atomic”是默认的行为( 注意,它实际上并不是一个关键字;它只是由缺lessnonatomic atomic 来指定的 – 在最近版本的llvm / clang中atomic被添加为关键字)。

假设你在@方法实现方法,primefaces与非primefaces改变生成的代码。 如果你正在编写你自己的setter / getters,atomic / nonatomic / retain / assign / copy只是build议性的。 (注意:@synthesize现在是LLVM最新版本中的默认行为,也不需要声明实例variables,它们也会自动合成,并在名称前加上_来防止意外的直接访问)。

对于“primefaces”,合成的setter / getter将确保整个值总是从getter返回或由setter设置,而不pipe任何其他线程上的setter活动。 也就是说,如果线程A位于getter的中间,而线程B调用setter,则实际的可用值 – 最有可能的自动释放对象 – 将在A中返回给调用者。

nonatomic ,没有这样的保证。 因此, nonatomic比“primefaces”快得多。

什么“primefaces”不做就是保证线程安全。 如果线程A同时调用getter和线程B和C调用不同值的setter,则线程A可能会返回三个返回值中的任何一个值 – 在任何setter被调用之前的值或者传入setters的任一值在B和C中。同样,对象可能以B或C的值为结束,无法分辨。

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

除此之外:

单个属性的atomicity性也不能保证多个相关属性在玩时的线程安全性。

考虑:

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

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

为了解决这个问题,你需要一个事务模型 。 即一些其他types的同步和/或排除,允许在更新从属属性时排除对fullName访问。

这在Apple的文档中有解释,但下面是一些实际发生的例子。 请注意,没有“primefaces”关键字,如果您不指定“非primefaces”,那么属性是primefaces的,但明确指定“primefaces”将导致错误。

 //@property(nonatomic, retain) UITextField *userName; //Generates roughly - (UITextField *) userName { return userName; } - (void) setUserName:(UITextField *)userName_ { [userName_ retain]; [userName release]; userName = userName_; } 

现在,primefaces变体有点复杂:

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

基本上,为了保证线程的安全性,primefaces版本必须locking,并且还要触发对象的引用计数(以及自动释放计数来平衡它),以保证调用者存在该对象,否则将存在如果另一个线程正在设置该值,则会导致竞争条件下降到0。

实际上这些东西有很多不同的变体,取决于属性是标量值还是对象,以及保留,复制,只读,非primefaces等等如何相互作用。 一般来说,房地产合成器只是知道如何做所有组合的“正确的事情”。

primefaces

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

非primefaces

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

理解差异的最好方法是使用下面的例子。

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

这使属性“名称”可读/写安全,但如果另一个线程D同时调用[name release] ,则此操作可能会导致崩溃,因为此处不涉及setter / getter调用。 这意味着对象是可读/写安全的(ATOMIC),但不是线程安全的,因为另一个线程可以同时向对象发送任何types的消息。 开发者应该确保这些对象的线程安全。

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

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

这三个function有什么区别?

我总是认为primefaces作为一个默认相当好奇。 在抽象层面上,我们使用一个类的primefaces属性作为实现100%线程安全的工具。 对于真正正确的multithreading程序,程序员的干预几乎肯定是一个要求。 同时,绩效特征和执行力度还没有深入细致。 这些年来,我写了一些大量multithreading的程序,因为primefaces对于任何目的都是不明智的,所以我一直宣称自己的属性nonatomic的。 在讨论这个问题的primefaces和非primefaces属性的细节时,我做了一些分析,遇到了一些好奇的结果。

执行

好。 我想要澄清的第一件事是locking实现是实现定义和抽象的。 路易斯在他的例子中使用@synchronized(self) – 我已经看到这是混淆的一个常见来源。 该实现并不实际使用@synchronized(self) ; 它使用对象级别的自旋锁 。 路易斯的插图很好的使用我们都熟悉的构造的高级插图,但重要的是要知道它不使用@synchronized(self)

另一个区别是primefaces属性会保留/释放循环你的对象内的吸气。

性能

这里有一个有趣的部分:在某些情况下,使用primefaces属性访问的性能在无争议的情况下(例如单线程)可能非常快。 在不太理想的情况下,使用primefaces访问会花费20倍以上的nonatomic开销。 虽然使用7线程的竞争案例是三字节结构(2.2 GHz 酷睿i7四核,x86_64)的44倍。 三字节结构是一个非常慢的属性的例子。

有趣的一面是:三字节结构的用户定义的访问器比合成的primefaces访问器快52倍; 或84%的合成非primefaces访问速度。

有争议的案件也可以超过50次。

由于实施方式的优化和变化的数量,在这些情况下衡量实际影响是相当困难的。 你可能经常会听到类似“信任它,除非你知道这是一个问题”。 由于抽象层次的影响,实际上很难测量实际影响。 从configuration文件中收集实际成本可能非常耗时,而且由于抽象,相当不准确。 此外,ARC与MRC可以有很大的不同。

所以让我们退后一步, 关注属性访问的实现,我们将包括像objc_msgSend这样的常见嫌疑犯,并且在无可争议的情况下(以秒为单位)对许多调用NSString getter的实际高级结果进行检查:

  • MRC | 非primefaces| 手动执行的getters:2
  • MRC | 非primefaces| 合成的吸气剂:7
  • MRC | primefaces| 合成的吸气剂:47
  • ARC | 非primefaces| 合成的getter:38(注意:这里ARC的joinref ref count)
  • ARC | primefaces| 合成的吸气剂:47

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

虽然我关注性能,但我仍然说语义学第一! 。 同时,对许多项目来说性能是一个低优先级。 但是,了解您使用的技术的执行细节和成本当然不会受到影响。 您应该使用正确的技术来满足您的需求,目的和能力。 希望这会为您节省几个小时的比较时间,并帮助您在devise程序时做出更明智的决定。

primefaces =线程安全

非primefaces =没有线程安全

线程安全:

如果实例variables在从多个线程访问时行为正确,则线程安全,而不pipe运行时环境对这些线程执行的调度或交错,以及调用代码没有额外的同步或其他协调。

在我们的情况下:

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

在哪里使用atomic

如果实例variables将在multithreading环境中访问。

atomic含义:

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

在哪里使用nonatomic

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

我在这里发现了一个非常好的解释primefaces和非primefaces属性。 以下是一些相同的文字:

“primefaces”意味着它不能被分解。 在操作系统/编程术语中,primefaces函数调用是不能被中断的 – 整个函数必须被执行,并且不会被操作系统通常的上下文切换切换出CPU,直到完成。 以防万一您不知道:由于CPU一次只能做一件事情,操作系统会在很短的时间段内将CPU的访问权限转移到所有正在运行的进程上,从而给出多任务的错觉 。 CPU调度程序可以(并且)在执行过程中的任何时刻中断进程 – 即使在调用中间函数时也是如此。 因此,对于像更新共享计数器variables这样的操作,其中两个进程可以同时更新variables,它们必须以primefaces方式执行,即每个更新操作必须先完成才能将任何其他进程交换到中央处理器。

所以我会猜测在这种情况下primefaces意味着属性读取器方法不能被打断 – 实际上是由方法读取的variables(s)不能改变他们的价值一半通过,因为其他线程/调用/函数获取交换到CPU上。

因为atomicvariables不能被中断,所以在任何时刻它们包含的值都是(线程locking的)保证是破坏的 ,尽pipe如此,确保这个线程locking使得对它们的访问速度更慢。 另一方面, non-atomicvariables并没有这样的保证,而是提供了更快速访问的奢侈品。 总结一下,当你知道你的variables不会被多个线程同时访问并加快速度的时候,用non-atomic去做。

在阅读了这么多文章,Stack Overflowpost和让演示应用程序检查variables属性属性后,我决定把所有的属性信息放在一起:

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

iOS中的variables属性或修饰符,你可以find所有上述的属性,这一定会帮助你。

  1. atomic

    • atomic意味着只有一个线程访问variables(静态types)。
    • atomic是线程安全的。
    • 但是performance慢
    • atomic是默认行为
    • 在非垃圾收集环境(即使用保留/释放/自动释放)中的primefaces访问器将使用锁来确保另一个线程不会干扰正确的设置/获取值。
    • 这实际上不是一个关键字。

    例:

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

    • nonatomic意味着multithreading访问variables(dynamictypes)。
    • nonatomic是线程不安全的。
    • 但是它的性能很快
    • nonatomic不是默认行为。 我们需要在属性属性中添加nonatomic关键字。
    • 当两个不同的进程(线程)同时访问同一个variables时,可能会导致意外的行为。

    例:

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

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

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

请参阅Apple的Objective-C 2.0文档的“ 性能和线程 ”部分,以获取更多信息以及创buildmultithreading应用程序时的其他注意事项。

primefaces:

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

如果你想象下面的函数在两个线程上同时发生,你可以看到为什么结果不会很漂亮。

 -(void) setName:(NSString*)string { if (name) { [name release]; // what happens if the second thread jumps in now !? // name may be deleted, but our 'name' variable is still set! name = nil; } ... } 

优点:每次完全初始化对象的返回都是multithreading的最佳select。

缺点:性能降低,执行速度稍慢

非primefaces:

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

优点:执行速度非常快。

缺点:在multithreading的情况下垃圾值的机会。

primefaces意味着只有一个线程访问variables(静态types)。 primefaces是线程安全的,但速度很慢。

非primefaces意味着多个线程访问variables(dynamictypes)。 非primefaces是线程不安全的,但速度很快。

没有这样的关键字“primefaces”

 @property(atomic, retain) UITextField *userName; 

我们可以使用上面的

 @property(retain) UITextField *userName; 

请参阅堆栈溢出问题我得到的问题,如果我使用@property(primefaces,保留)NSString * myString

primefaces是线程安全的速度 ,它确保(不保证)只有locking值被提供,而不pipe有多less线程正在尝试访问相同的区域。 当使用atomic时,写在这个函数内的一段代码成为关键部分的一部分,一次只能执行一个线程。

只保证线程安全; 它并不能保证。 我的意思是你为你的汽车聘请专家司机,但是并不能保证汽车不会遇到事故。 然而,可能性仍然是丝毫的。

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

代码对话:

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

 self.myProperty = value; 

是线程安全的。

 [myArray addObject:@"Abc"] 

不是线程安全的。

默认atomic ,这意味着无论何时使用该属性,性能都会降低性能,但是它是线程安全的。 Objective-C所做的是设置一个锁,所以只要实际的线程可以访问variables,只要setter / getter被执行。

具有ivar属性的MRC示例_internal:

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

所以最后两个是一样的:

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

另一方面, nonatomic没有添加任何代码。 所以如果你自己编写安全机制,它只是线程安全的。

 @property(nonatomic, retain) UITextField *userName; 

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

不要忘记,这并不意味着整个财产是线程安全的。 只有setter / getter的方法调用是。 但是如果你使用一个setter,然后在两个不同的线程同时使用一个getter,它也可能被打破!

如果你在multithreading代码中使用你的属性,那么你将能够看到非primefaces和primefaces属性之间的差异。 非primefaces比primefaces快,primefaces是线程安全的,而不是非primefaces的。

Vijayendra Tripathi已经给出了一个multithreading环境的例子。

primefaces(默认)

primefaces是默认的:如果你不input任何东西,你的属性是primefaces的。 一个primefaces属性是保证,如果你尝试读取它,你会得到一个有效的值。 它不能保证这个价值是什么,但是你会收回好的数据,而不仅仅是垃圾内存。 这可以让你做的是,如果你有多个线程或多个进程指向一个variables,一个线程可以读取,另一个线程可以写入。 如果他们在同一时间点击,读者线程保证得到两个值中的一个:在改变之前或在改变之后。 什么primefaces不给你是任何forms的保证,你可能会得到哪些价值观。 primefaces通常与线程安全混淆,这是不正确的。 你需要保证你的线程安全。 然而,primefaces将保证,如果你尝试阅读,你会得到某种价值。

非primefaces

另一方面,正如你可能猜测的那样,非primefaces的意思就是“不要做那些primefaces性的东西”。你失去的就是保证你总是找回东西。 如果您在写入过程中尝试读取数据,则可能会返回垃圾数据。 但是,另一方面,你走得更快一点。 因为primefaces属性必须做一些魔术来保证你会得到一个值,所以它们会慢一点。 如果这是一个属性,你正在访问很多,你可能想下降到非primefaces,以确保你没有招致速度的惩罚。

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

在讨论@property的属性之前,你应该知道@property有什么用处。 @property提供了一种定义类打算封装的信息的方法。 如果你使用@property声明一个对象/variables,那么这个对象/variables将被其他类导入其类。 如果在头文件中使用@property声明对象,则必须在实现文件中使用@synthesize进行合成。

例:

.h类

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

.m类

 @implementation ExampleClass @synthesize name; @end 

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

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

@property的属性列表:primefaces。 非primefaces。 保留。 复制。 只读。 读写。 分配。 强大。

primefaces:这是默认行为。 如果一个对象被声明为primefaces,那么它就变成了线程安全的。 线程安全的手段,一次只有该类的特定实例的一个线程可以控制该对象。

例如:

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

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

保留:当属性是一个指向对象的指针时是必需的。setter方法将增加对象的保留数量,以便它将占用自动释放池中的内存。 @property (retain)NSString *name;

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

 @property (copy) NSString *name; NSMutableString *nameString = [NSMutableString stringWithString:@"Liza"]; xyzObj.name = nameString; [nameString appendString:@"Pizza"]; 

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

readwrite:是默认行为。 您不需要明确指定readwrite属性。

@property (readwrite) NSString *name;

assign:将生成一个setter,它将值直接分配给实例variables,而不是复制或保留它。 This is best for primitive types like NSInteger and CGFloat, or objects you don't directly own, such as delegates.

@property (assign) NSInteger year;

strong: is a replacement for retain. @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.

@property (unsafe_unretained) NSObject *unsafeProperty;

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

At the same time if you call

 [self setName:@"Datta"] 

from thread B ,

Now If *name property is nonatomic then

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

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

Now If *name property is atomic

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

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

Such situation operation will perform serially. And Slow in performance

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

– Nonatomic is thread unsafe.

– but it is fast in performance

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

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

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

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

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.

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


atomic will ALWAYS guarantee

  • If two different people want to read and write at the same time, your paper won't just burn! –> Your application will never crash, even in a race condition.
  • If one person is trying to write and has only 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', ie if there are 8 bytes to bytes to be written, and only 4 bytes are written——up to that moment, you are not allowed to read from it. But since I said it won't crash then it would read from the value of an autoreleased object.
  • If before writing you have erased that which was previously written on paper and then someone wants to read you can still read. 怎么样? 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.

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

  • Atomic doesn't guarantee thread safety, though 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.

Wait what?! Are multithreading and thread safety different?

是。 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.
  • 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.

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

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

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.

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.

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

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

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

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