Which is threadsafe atomic or non atomic?
我搜索并发现不可变是线程安全的,而可变不是。这很好。但是我得到了误导性的笔记、博客、关于线程安全的原子和非原子的答案,请对答案作出解释。
假设有一个名为"name"的原子字符串属性,如果从线程a调用
如果属性"name"是非原子的,那么上面示例中的所有线程(a、b、c和d)都将同时执行,从而产生任何不可预知的结果。在原子的情况下,a、b或c中的任何一个将首先执行,但d仍然可以并行执行。
您对此的评论将有助于我们……
我的问题是,"可可中的哪一种是安全的,原子的还是非原子的?"
对于objc属性——线程安全也是如此。
Atomic更能抵抗线程错误。总的来说,这是一个奇怪的违约。你喜欢原子的场景很少。原子可以增加正确性的概率,但它的级别太低,不能被认为是适当锁定机制的替代品。因此,如果您需要线程安全,您仍然需要原子读/写之上的其他同步原语。如果您不需要线程安全(例如,实例是不可变的,或者只打算从主线程运行),那么Atomic将不会添加任何内容。
抵抗线程错误不是一种"质量"——它可以掩盖真正的线程错误,使它们更难重现和检测。
还要注意,可变类型和不可变类型实际上不能保证线程安全。在objc名称中,mutable'只能用于引用接口——不可变实例的内部实际上可能具有内部可变状态。简而言之,不能假定具有可变子类的类型是线程安全的。
问题扩展:
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 operation on different thread will be performed serially which means if one thread is executing setter or getter, then other threads will wait.
如果所有线程同时尝试读取和/或写入属性,那么一次只有一个线程有访问权,如果属性是原子的,其他线程将被阻止。如果属性是非原子的,那么它们都将同时拥有对变量的无保护读写访问权。
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.
嗯,还有很多。常见的例子是:
1 2 3 4 5 6 7 8 | @interface MONPerson : NSObject @property (copy) NSString * firstName; @property (copy) NSString * lastName; - (NSString *)fullName; @end |
原子的或非原子的,如果一个线程正在从该实例读取,而另一个线程正在向其写入,则需要一个同步机制(例如锁)。您可能会得到一个monperson的firstname和另一个firstname——对象可能在getter的返回值返回给您之前发生了更改,或者这可能发生:
线程A:
1 | p.firstName = @"Rob"; |
线程B:
1 | p.firstName = @"Robert"; |
线程A:
1 | label.string = p.firstName; // << uh, oh -- will be Robert |
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. Kindly comment on this....
对的。但是如果你看上面的例子——单原子很少是锁的合适替代品。它必须看起来像这样:
线程A:
1 2 3 4 5 6 7 | [p lock]; // << wait for it… … … … // Thread B now cannot access p p.firstName = @"Rob"; NSString fullName = p.fullName; [p unlock]; // Thread B can now access p label.string = fullName; |
线程B:
1 2 3 4 | [p lock]; // << wait for it… … … … // Thread A now cannot access p … [p unlock]; |
原子存取器的平均速度比非原子存取慢20倍以上。另外,如果您的类需要是threadsafe并且具有可变状态,那么当它在并发场景中运行时,您可能最终会使用锁。正确的锁定提供了您所需要的所有保证——在这种情况下,原子访问器是多余的,使用原子只会增加CPU时间。常规锁的另一个好处是,您拥有所需的所有粒度——尽管它通常比原子使用的自旋锁重,但您通常需要较少的获取,因此,如果正确使用常规锁,最终会非常快。
原子保证对变量的原子访问,但它不会使代码线程安全。非原子也不是。
对于"原子",合成的setter/getter方法将确保始终从getter返回一个完整的值或由setter设置,而不管其他线程上的setter活动如何。因此,如果线程A在getter的中间,而线程B调用setter,那么实际的可行值将返回到a中的调用者。对于非原子的,您没有这样的保证。
原子使执行以下线程安全。
1 | self.myProperty = value; |
或
1 | id value = self.myProperty |
它不会使下列线程安全
1 | [myPorperty addObject:value]; |
原子使设置或获取属性成为线程安全的,但它不使调用该属性本身的任何方法成为线程安全的。
设置或获取值可能需要一个以上的CPU指令,这意味着设置或获取可以中途中断,另一个线程可以做一些事情,使上一个线程的设置或获取值的进度无效。
Atomic说以某种方式设置或获取值,这样它就像发生在一个不可分割的指令中一样发生,所以没有其他线程可以跨出一半来把事情搞砸。
不可变对象是线程安全的简单方法,因为您不能更改它们,因为您可以从一个不可变对象更改一个属性,从而使该部分不安全,除非您使其成为原子对象。
还有一个"原子"属性没有提到,这是在ARC之前线程安全所必需的(可能仍然是)。首先解释为什么需要它:假设没有ARC,您读取一个对象属性并立即保留它。但另一个线程可能正好在您读取属性和retain调用之间出现,将object属性设置为nil,导致对象被释放。将retain发送到未释放的对象,该对象不正常。这将是一个非常罕见的错误,因为它只发生在正确的时机。为了防止这种情况发生,原子对象属性总是返回自动释放的对象。
1)两者都是非线程安全的。2)Atomic只具有读写安全性。3)但是,如果要使线程安全,需要实现一些锁机制,例如互斥锁、旋转锁。多读…https://developer.apple.com/library/ios/documentation/cocoa/conceptive/multiphreading/threadsafety/threadsafety.html
你应该考虑实现一个锁定机制,这样你就不会在你的应用程序中出现死锁。另外,如果您正在实现核心数据,那么您应该阅读IOS线程安全性。
看。
http://developer.apple.com/library/ios/documentation/cocoa/conceptive/multiphreading/threasafetysummary/threasafetysummary.html
http://developer.apple.com/library/ios/documentation/cocoa/conceptive/multiphreading/threadsafety/threadsafety.html%23//apple_-ref/doc/uid/10000057i-ch8-sw1
非原子是线程安全的。保证获得变量的值。