Sun*_*day 8 properties objective-c nonatomic
在Objective-C中为基本类型指定属性是否有意义nonatomic?
我想知道这两个属性之间的区别:
@property (nonatomic) BOOL myBool;
@property BOOL myBool;
Run Code Online (Sandbox Code Playgroud)
Rhu*_*arb 25
答案在技术上是肯定的它们是不同的,但实际上并非它们不是,除非你编写自己的访问器.
让我解释.对于对象指针属性,假设@property NSObject *foo在使用合成访问器时生成的代码存在明显且重要的差异.这在Apple文档中有描述,它指出如果属性是原子的,则合成访问器将锁定对象(如果未指定非原子,则默认情况下它将变为原子)
所以对于对象属性在一个非常粗略的概述:非原子更快但不是线程安全,原子(你不能指定它,但它的默认值)是线程安全但可能更慢.
(注:如果你习惯了Java,则可以考虑使用的nonatomic像不指定synchronized,而不是指定nonatomic的,如指定synchronized换句话说原子=同步.)
但是BOOL是一个原语 - 实际上是一个C签名的char,所以访问应该是原子的,而不是像Jano的回答中提到的那样锁定对象.所以当你合成访问器时,有两种可能性:1:编译器是智能的,看到属性是原始的并且避免锁定它,2:编译器总是锁定对象的原子属性
据我所知,这在任何地方都没有记录,所以我尝试使用XCode中的Generate-> Assembly选项并进行比较.答案并不是完全确定的,但足以说我几乎可以肯定答案是#1,编译器很聪明.我这样说,因为为原子对象属性生成的汇编代码与非原子对象属性有很大不同(更多):这是锁定对象的所有代码.另一方面,对于BOOL属性,只有一行不同 - 单个"mov"看起来不像它可能会有所不同.我还是想知道.有趣的是,另一个区别是BOOL的原子版本有一些额外的注释轮廓用于调试 - 所以编译器显然对它的处理方式不同.
尽管如此,我认为它们的相似之处在于实际目的.
但是它们在技术上仍然存在差异,并且如果你看不到实现,那么你正在阅读的其他一些库(你自己没有自己编写代码)可能会有很大的不同,这就是原因:原子属性有契约.合同说:"如果您在多个线程上访问我的值,我保证每个设置或获取操作将在任何其他线程开始之前完成".
但是,你说,BOOL仍然是自然原子的,所以这个契约不是隐含的吗?
不.BOOL 变量自然是原子的,但我们谈的是属性.一个属性可能无法合成,甚至可能不会有一个变量来支持它.这实际上很常见.考虑:
@property (getter=isEmptyThingo) BOOL emptyThingo;
...
- (BOOL)isEmptyThingo
{
Thingo *thingo = [self deriveTheThingo];
if ([thingo length] == 0) {
return YES;
}
return NO;
}
Run Code Online (Sandbox Code Playgroud)
谁知道发生了什么事deriveTheThingo?好吧,这有点做作,但关键是isEmptyThingo - 我们的getter看起来不是原子,是吗?如果一个线程正在派生thingo而另一个线程调用以查找它是否为空,会发生什么.
长话短说:财产不是原子的.所以我们应该这样宣布.
因此m原始答案合格:如果你自己编写这个属性并使用@synthesize,那么它们可能是相同的,但你通常不应该对它们进行同样的处理.
根据经验,如果您不需要多线程支持 - 如果您在UIViewControllers等UI代码中工作,通常不需要多线程支持,那么只需将其声明为非原子的.
在x位架构(例如:32位,64位等)中,任何x或更小位的值将始终以原子方式读取或写入.这是任何理智的硬件实现的属性.
默认的原子属性意味着始终设置或获取属性值,而忽略其他线程正在执行的操作.这只是超出体系结构位数的属性的一个问题.编译器在任何其他类型上完全忽略Nonatomic.
例:
@property struct { int d; } flag;
@property (atomic) struct { float x; float y; } point;
@property (atomic,copy) NSString *s;
Run Code Online (Sandbox Code Playgroud)
struct { int d; } 已经是原子的,所以加法器不需要相互排斥.
struct { float x, float y}如果它不是原子的,则可能处于不一致的状态.示例:两个线程设置{1,2}并且{3,4}可能与写入重叠,结构可能最终得到每个集合的值:{1,4}.
原子属性有助于线程安全,避免导致不一致的值或内存管理失败的竞争条件.仅此一项并不能保证线程安全,因为它不会处理其他问题,如死锁,饥饿,可见性等.
| 归档时间: |
|
| 查看次数: |
5113 次 |
| 最近记录: |