Ale*_*yne 1828 properties atomic objective-c ios nonatomic
财产申报中的含义atomic和nonatomic含义是什么?
@property(nonatomic, retain) UITextField *userName;
@property(atomic, retain) UITextField *userName;
@property(retain) UITextField *userName;
Run Code Online (Sandbox Code Playgroud)
这三者之间的运作区别是什么?
bbu*_*bum 1747
最后两个是相同的; "atomic"是默认行为(请注意,它实际上不是关键字;仅在缺少时指定 - nonatomicatomic在最近版本的llvm/clang中添加为关键字).
假设你是@synthesizing方法实现,原子与非原子会改变生成的代码.如果您正在编写自己的setter/getter,则atomic/nonatomic/retain/assign/copy仅仅是建议性的.(注意:@synthesize现在是LLVM的最新版本中的默认行为.也不需要声明实例变量;它们也将自动合成,并且将_在其名称前加上以防止意外直接访问).
使用"atomic",合成的setter/getter将确保始终从getter返回整个值或由setter设置,而不管任何其他线程上的setter活动.也就是说,如果线程A位于getter的中间,而线程B调用setter,则实际可行的值 - 一个自动释放的对象,很可能 - 将返回给A中的调用者.
在nonatomic,没有这样的保证.因此,nonatomic比"原子"快得多.
什么"原子"并没有做的就是关于线程安全的任何保证.如果线程A与线程B同时调用getter并且C调用具有不同值的setter,则线程A可以获得返回的三个值中的任何一个 - 在调用任何setter之前的值或者传递给setter的任一值在B和C中.同样,对象最终可能会得到B或C的值,无法分辨.
确保数据完整性 - 多线程编程的主要挑战之一 - 是通过其他方式实现的.
添加到此:
atomicity 当多个相关属性在起作用时,单个属性也不能保证线程安全.
考虑:
@property(atomic, copy) NSString *firstName;
@property(atomic, copy) NSString *lastName;
@property(readonly, atomic, copy) NSString *fullName;
Run Code Online (Sandbox Code Playgroud)
在这种情况下,线程A可以通过调用setFirstName:然后调用来重命名对象setLastName:.同时,线程B可以fullName在线程A的两个调用之间调用,并且将接收与旧的姓氏一起的新的名字.
要解决此问题,您需要一个事务模型.即一些其他类型的同步和/或排除,允许fullName在更新依赖属性时排除对访问的访问.
Lou*_*arg 358
这在Apple的文档中有解释,但下面是一些实际发生的例子.请注意,没有"atomic"关键字,如果未指定"nonatomic",则属性为atomic,但明确指定"atomic"将导致错误.
//@property(nonatomic, retain) UITextField *userName;
//Generates roughly
- (UITextField *) userName {
return userName;
}
- (void) setUserName:(UITextField *)userName_ {
[userName_ retain];
[userName release];
userName = userName_;
}
Run Code Online (Sandbox Code Playgroud)
现在,原子变体有点复杂:
//@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_;
}
}
Run Code Online (Sandbox Code Playgroud)
基本上,原子版本必须采取锁定以保证线程安全,并且还会碰撞对象的引用计数(以及自动释放计数以平衡它),以便保证对象存在对象,否则存在如果另一个线程正在设置该值,则是一个潜在的竞争条件,导致引用计数降至0.
实际上有很多不同的变体,这些东西的工作方式取决于属性是标量值还是对象,以及保留,复制,只读,非原子等交互方式.一般来说,属性合成器只知道如何为所有组合做"正确的事情".
raw*_*w3d 167
Vij*_*dra 134
理解差异的最佳方法是使用以下示例.
假设存在一个名为"name"的原子字符串属性,如果[self setName:@"A"]从线程A调用,[self setName:@"B"]从线程B调用,并[self name]从线程C 调用,则不同线程上的所有操作将按顺序执行,这意味着一个线程正在执行一个setter或者getter,然后其他线程将等待.
这使得属性"name"读/写安全,但如果另一个线程D [name release]同时调用,则此操作可能会产生崩溃,因为此处不涉及setter/getter调用.这意味着对象是读/写安全的(ATOMIC),但不是线程安全的,因为另一个线程可以同时向对象发送任何类型的消息.开发人员应确保此类对象的线程安全.
如果属性"name"是非原子的,那么上面例子中的所有线程--A,B,C和D将同时执行,产生任何不可预测的结果.在原子的情况下,A,B或C中的任何一个将首先执行,但D仍然可以并行执行.
jus*_*tin 114
这个问题的其他优秀答案已经很好地定义了语法和语义.由于执行和性能不够详细,我将添加我的答案.
这三种功能有什么区别?
我一直认为原子作为一个非常好奇的默认.在抽象层面,我们致力于将类的原子属性用作实现100%线程安全性的工具,这是一个极端情况.对于真正正确的多线程程序,程序员的干预几乎肯定是必需的.同时,性能特征和执行还没有详细说明.多年来编写了一些大量多线程的程序后,我一直在声明我的属性,nonatomic因为原子对任何目的都不合理.在讨论原子和非原子属性的细节这个问题时,我做了一些分析,遇到了一些奇怪的结果.
执行
好.我想要澄清的第一件事是锁定实现是实现定义和抽象的.路易斯@synchronized(self)在他的例子中使用- 我已经将此视为混淆的常见原因.实施实际上并没有使用@synchronized(self); 它使用对象级旋转锁.路易斯的插图对于使用我们都熟悉的结构的高级插图是有益的,但重要的是知道它不使用@synchronized(self).
另一个区别是原子属性将保留/释放你的对象在getter中.
性能
这是有趣的部分:在无争议(例如单线程)情况下使用原子属性访问的性能在某些情况下可能非常快.在不太理想的情况下,使用原子访问的成本可能是开销的20倍以上nonatomic.虽然使用7个线程的Contested案例对于三字节结构(2.2 GHz Core i7四核,x86_64)来说慢了44倍.三字节结构是一个非常慢的属性的例子.
有趣的注意事项:三字节结构的用户定义访问器比合成的原子访问器快52倍; 或84%的合成非原子访问器的速度.
有争议案件中的物品也可超过50次.
由于实施中的优化和变化的数量,在这些环境中测量实际影响是非常困难的.您可能经常会听到"信任它,除非您分析并发现它是一个问题".由于抽象级别,实际上很难衡量实际影响.从配置文件收集实际成本可能非常耗时,并且由于抽象,非常不准确.同样,ARC vs MRC可以产生很大的不同.
所以让我们退一步,不再关注属性访问的实现,我们将包括通常的嫌疑人objc_msgSend,并检查一些真实的高级结果,以便NSString在无争议的情况下(以秒为单位的值)多次调用getter :
正如您可能已经猜到的那样,引用计数活动/循环是原子学和ARC下的重要贡献者.您还会看到有争议案件的更大差异.
虽然我非常关注性能,但我仍然说Semantics First!.同时,性能是许多项目的低优先级.但是,了解您使用的技术的执行细节和成本肯定不会受到伤害.您应该根据自己的需要,目的和能力使用正确的技术.希望这可以节省您几个小时的比较,并帮助您在设计程序时做出更明智的决策.
Dur*_*n.H 96
原子 =螺纹安全
非原子 =无线程安全
如果实例变量在从多个线程访问时表现正确,则它们是线程安全的,无论运行时环境是否调度或交错执行这些线程,并且调用代码没有额外的同步或其他协调.
如果线程更改了实例的值,则更改的值可用于所有线程,并且只有一个线程可以一次更改该值.
atomic:如果要在多线程环境中访问实例变量.
atomic:没有那么快,nonatomic因为nonatomic运行时不需要任何看门狗工作.
nonatomic:如果实例变量不会被多个线程更改,您可以使用它.它提高了性能.
tip*_*low 69
我发现原子和非原子性的一个很好的解释放在这里.以下是相同的相关文字:
'原子'意味着它不能被分解.在OS /编程术语中,原子函数调用是一个不能被中断的函数 - 整个函数必须执行,并且不会被操作系统通常的上下文切换换出CPU直到它完成.以防你不知道:由于CPU一次只能做一件事,操作系统会在很短的时间内将CPU的访问权限转移到所有正在运行的进程,从而产生多任务处理的错觉.CPU调度程序可以(并且确实)在执行过程中的任何时刻中断进程 - 即使在函数调用中期也是如此.因此,对于更新共享计数器变量的操作,其中两个进程可以尝试同时更新变量,它们必须"原子地"执行,即每个更新操作必须完全完成才能将任何其他进程交换到中央处理器.
所以我猜测在这种情况下原子意味着属性读取器方法不能被中断 - 实际上意味着方法读取的变量不能在中途改变它们的值,因为其他一些线程/调用/函数得到了交换到CPU上.
因为atomic变量不能被中断,所以它们在任何一点所包含的值都是(线程锁定)保证不会被破坏,但是,确保这种线程锁定会使它们的访问速度变慢.non-atomic另一方面,变量没有这样的保证,但确实提供了更快捷的访问.总结一下,non-atomic当你知道你的变量不会被多个线程同时访问并加快速度时,请继续.
swi*_*Boy 66
阅读了这么多文章后,Stack Overflow发布并制作了演示应用程序以检查变量属性属性,我决定将所有属性信息放在一起:
atomic //默认nonatomicstrong = retain //默认weak = unsafe_unretainedretainassign //默认unsafe_unretainedcopyreadonlyreadwrite //默认在iOS中的变量属性属性或修饰符一文中,您可以找到所有上述属性,这肯定会对您有所帮助.
atomic
atomic 表示只有一个线程访问变量(静态类型).atomic 是线程安全的.atomic 是默认行为例:
@property (retain) NSString *name;
@synthesize name;
Run Code Online (Sandbox Code Playgroud)nonatomic
nonatomic 表示多线程访问变量(动态类型).nonatomic 线程不安全.nonatomic不是默认行为.我们需要nonatomic在property属性中添加关键字.例:
@property (nonatomic, retain) NSString *name;
@synthesize name;
Run Code Online (Sandbox Code Playgroud)And*_*ant 54
原子保证访问属性将以原子方式执行.例如,它总是返回一个完全初始化的对象,一个线程上的任何属性的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;
}
...
}
Run Code Online (Sandbox Code Playgroud)
优点: 每次返回完全初始化的对象是多线程情况下的最佳选择.
缺点: 性能受到影响,使执行速度变慢
与Atomic不同,它不能确保每次完全初始化对象返回.
优点: 执行速度极快.
缺点: 多线程情况下垃圾价值的可能性.
IOS*_*cks 31
原子意味着只有一个线程访问变量(静态类型).Atomic是线程安全的,但它很慢.
Nonatomic意味着多个线程访问变量(动态类型).Nonatomic是线程不安全的,但速度很快.
小智 14
Atomic是线程安全的,它很慢并且很好地保证(不保证)无论有多少线程尝试通过同一区域访问,都只提供锁定值.使用atomic时,在此函数内部编写的一段代码将成为临界区的一部分,一次只能执行一个线程.
它只保证线程安全; 它并不保证.我的意思是你为你的汽车聘请专家司机,但它不能保证汽车不会发生事故.但是,概率仍然是最轻微的.
原子 - 它不能被分解,所以结果是预期的.使用非原子 - 当另一个线程访问内存区域时,它可以修改它,因此结果是意外的.
代码谈话:
Atomic使得属性线程的getter和setter安全.例如,如果你写了:
self.myProperty = value;
Run Code Online (Sandbox Code Playgroud)
是线程安全的.
[myArray addObject:@"Abc"]
Run Code Online (Sandbox Code Playgroud)
不是线程安全的.
Dee*_*pak 13
没有这样的关键字"原子"
@property(atomic, retain) UITextField *userName;
Run Code Online (Sandbox Code Playgroud)
我们可以使用上面这样的
@property(retain) UITextField *userName;
Run Code Online (Sandbox Code Playgroud)
请参阅Stack Overflow 问题如果我使用@property(atomic,retain)NSString*myString,我会遇到问题.
Bin*_*ian 11
在默认情况下是atomic,这意味着它无论您何时使用属性花费你的表现,但它是线程安全的.Objective-C的作用是设置一个锁,只要实际的线程可以访问变量,只要执行setter/getter.
带有ivar _internal的属性的MRC示例:
[_internal lock]; //lock
id result = [[value retain] autorelease];
[_internal unlock];
return result;
Run Code Online (Sandbox Code Playgroud)
所以最后两个是相同的:
@property(atomic, retain) UITextField *userName;
@property(retain) UITextField *userName; // defaults to atomic
Run Code Online (Sandbox Code Playgroud)
另一方面,确实nonatomic没有为您的代码添加任何内容.因此,如果您自己编写安全机制,那么它只是线程安全的.
@property(nonatomic, retain) UITextField *userName;
Run Code Online (Sandbox Code Playgroud)
根本不必将关键字写为第一个属性属性.
不要忘记,这并不意味着整个属性是线程安全的.只有setter/getter的方法调用才是.但是如果你使用一个setter,然后使用2个不同的线程同时使用一个getter,那么它也可能被破坏!
Pro*_*ton 11
原子(默认)
默认为Atomic:如果您不键入任何内容,则属性是原子的.保证原子属性如果您尝试从中读取,则将返回有效值.它不会保证该值可能是什么,但是您将获得良好的数据,而不仅仅是垃圾内存.这允许您做的是,如果您有多个线程或多个进程指向单个变量,一个线程可以读取而另一个线程可以写入.如果它们同时命中,则读者线程保证获得两个值中的一个:在更改之前或在更改之后.什么原子能不给你任何关于你可能得到的那些价值的保证.原子通常与线程安全混淆,这是不正确的.您需要以其他方式保证您的线程安全.但是,原子将保证,如果你试图阅读,你会得到一些价值.
非原子
另一方面,正如你可能猜到的那样,非原子,只是意味着,"不要做那些原子的东西."你失去的是保证你总能得到回报.如果您尝试在写入过程中读取,则可以获取垃圾数据.但是,另一方面,你会更快一点.因为原子属性必须做一些魔术来保证你会得到一个值,它们会慢一些.如果它是您正在访问的属性,您可能需要下拉到非原子,以确保您不会产生速度惩罚.
在此处查看更多信息:https://realm.io/news/tmi-objective-c-property-attributes/
小智 9
如果您在多线程代码中使用属性,那么您将能够看到非原子属性和原子属性之间的区别.非原子比原子快,原子是线程安全的,而不是非原子的.
Vijayendra Tripathi已经为多线程环境提供了一个例子.
开始之前:您必须知道内存中的每个对象都需要从内存中释放出来才能使新编写器发生.你不能像在纸上那样简单地写一些东西.你必须首先擦除(dealloc)它,然后你可以写它.如果擦除完成(或完成一半)并且尚未编写任何内容(或写入一半)并且您尝试阅读它可能会非常有问题!原子和非原子帮助您以不同方式处理此问题.
首先阅读这个问题,然后阅读Bbum的答案.另外,然后阅读我的总结.
atomic 总是保证
保留计数是在Objective-C中管理内存的方式.创建对象时,它的保留计数为1.当您向对象发送保留消息时,其保留计数将增加1.当您向对象发送释放消息时,其保留计数将减1.当您向对象发送自动释放消息,其保留计数在将来的某个阶段递减1.如果对象的保留计数减少到0,则将其取消分配.
什么?!多线程和线程安全性有何不同?
是.多线程意味着:多个线程可以同时读取共享数据,但我们不会崩溃,但它并不能保证您不会读取非自动释放的值.通过线程安全,可以保证您所读取的内容不会自动释放.我们默认情况下不会使所有内容成为原子的原因是,存在性能成本,并且对于大多数事情而言并不需要线程安全.我们的代码的一些部分需要它,对于那些少数部分,我们需要使用锁,互斥或同步以线程安全的方式编写代码.
nonatomic
总的来说,他们在两个方面有所不同
是否因为拥有或不拥有自动释放池而崩溃.
允许在"尚未完成的写入或空值"的中间读取,或者不允许并且仅在完全写入值时允许读取.
如何申报:
因为原子是默认的,所以
@property (retain) NSString *name;
Run Code Online (Sandbox Code Playgroud)
并在实现文件中
self.name = @"sourov";
Run Code Online (Sandbox Code Playgroud)
假设与三个属性相关的任务是
@property (retain) NSString *name;
@property (retain) NSString *A;
@property (retain) NSString *B;
self.name = @"sourov";
Run Code Online (Sandbox Code Playgroud)
所有属性并行工作(如异步).
如果从线程A中调用"name" ,
和
如果你打电话的话
[self setName:@"Datta"]
Run Code Online (Sandbox Code Playgroud)
来自主题B,
现在如果*name属性是非原子的那么
这就是为什么非原子被称为线程不安全但是由于并行执行它的性能很快
现在如果*name属性是原子的
这就是为什么原子被称为线程安全, 这就是为什么它被称为读写安全
这种情况操作将连续执行. 表现缓慢
- Nonatomic意味着多线程访问变量(动态类型).
- Nonatomic是线程不安全的.
- 但它的性能很快
-Nonatomic不是默认行为,我们需要在属性属性中添加非原子关键字.
对于In Swift确认Swift属性在ObjC意义上是非原子的.一个原因是你要考虑每个属性的原子性是否足以满足你的需求.
参考:https://forums.developer.apple.com/thread/25642
欲了解更多信息,请访问网站 http://rdcworld-iphone.blogspot.in/2012/12/variable-property-attributes-or.html
原子性(默认)
Atomic 是默认值:如果您不输入任何内容,则您的属性是 atomic。原子属性保证,如果您尝试从中读取,您将获得一个有效值。它不保证该值可能是多少,但您将获得良好的数据,而不仅仅是垃圾内存。这允许您做的是,如果您有多个线程或多个进程指向一个变量,一个线程可以读取而另一个线程可以写入。如果它们同时命中,则保证读取器线程获得两个值之一:更改之前或更改之后。atomic 不能为您提供关于您可能获得哪些值的任何保证。Atomic 通常与线程安全混淆,这是不正确的。您需要以其他方式保证您的线程安全。
非原子的
另一方面,非原子的,正如你可能猜到的,只是意味着,“不要做那些原子的东西。” 你失去的是保证你总能得到一些东西。如果您尝试在写入过程中读取,您可能会取回垃圾数据。但是,另一方面,你走得更快一点。因为原子属性必须做一些魔法来保证你会得到一个值,所以它们有点慢。如果它是一个您经常访问的属性,您可能希望降到非原子属性,以确保您不会招致速度损失。使用权
礼貌https://academy.realm.io/posts/tmi-objective-c-property-attributes/
原子性属性属性(原子性和非原子性)并未反映在相应的 Swift 属性声明中,但是当从 Swift 访问导入的属性时,Objective-C 实现的原子性保证仍然有效。
所以?—?如果你在 Objective-C 中定义了一个原子属性,它在被 Swift 使用时将保持原子性。
礼貌 https://medium.com/@YogevSitton/atomic-vs-non-atomic-properties-crash-course-d11c23f4366c
无论有多少线程正在执行getter和setter方法,atomic属性都确保保留完全初始化的值。
nonatomic属性指定合成的访问器仅直接设置或返回一个值,而不保证如果从不同的线程同时访问相同的值会发生什么情况。
| 归档时间: |
|
| 查看次数: |
473849 次 |
| 最近记录: |