ios Objective-C 中的原子属性与线程安全
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21098494/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Atomic properties vs thread-safe in Objective-C
提问by Doug Smith
In most of the discussions I've read, it indicates that making a property atomic does not guarantee it to be thread-safe, it just guarantees that the value returned won't be garbage as a result of one object writing to it and another trying to read it at the same time.
在我读过的大多数讨论中,它表明使属性原子化并不能保证它是线程安全的,它只是保证返回的值不会因为一个对象写入它而另一个对象是垃圾试图同时阅读它。
I understand this isn't thread-safe as a third object could be writing it and while the object accessing it wouldn't get garbage back, it's not entirely certain which value it will get back as multiple objects are writing to it at the same time, and it may get any of their values.
我知道这不是线程安全的,因为第三个对象可能正在写入它,虽然访问它的对象不会返回垃圾,但并不完全确定它将返回哪个值,因为多个对象同时写入它时间,它可能会得到它们的任何值。
So when we say it won't return garbage, would garbage be in the sense that if an object was non-atomic and an object tried to access it while another was writing to it, it might get the result back mid-write, and only get a partial, incomplete version of the change brought about by the write? Is this what "garbage" means in this sense, and what atomic properties help to prevent?
所以当我们说它不会返回垃圾时,垃圾是否是指如果一个对象是非原子的,并且一个对象在另一个正在写入它的时候试图访问它,它可能会在写入过程中得到结果,并且只得到部分、不完整版本的写入带来的变化?这就是“垃圾”在这个意义上的含义,以及哪些原子特性有助于防止?
回答by Binarian
An atomic
property in Objective C guarantees that you will never see partial writes.
When a @property
has the attribute atomic
it is impossible to only partially write the value. The setter is like that:
atomic
Objective C 中的属性保证您永远不会看到部分写入。当 a@property
具有属性时atomic
,不可能仅部分写入该值。setter 是这样的:
- (void)setProp:(NSString *)newValue {
[_prop lock];
_prop = newValue;
[_prop unlock];
}
So if two threads want to write the value @"test"
and @"otherTest"
at the same time, then
at any given time the property can only be the initial value of the property or @"test"
or @"otherTest"
.
nonatomic
is faster but the value is a garbage value and no partial String of @"test"
/@"otherTest"
(thx @Gavin) or any other garbage value.
因此,如果两个线程想要写的价值@"test"
,并@"otherTest"
在同一时间,然后在任何给定的时间属性只能是财产或初始值@"test"
或@"otherTest"
。
nonatomic
更快,但该值是一个垃圾值,没有@"test"
/ @"otherTest"
(thx @Gavin) 或任何其他垃圾值的部分字符串。
Butatomic
is only thread-safe with simple use.
It is not garantueed.
Appledocsays the following:
但atomic
只有简单使用的线程安全。这不是保证。
Appledoc说如下:
Consider an
XYZPerson
object in which both a person's first and last names are changed using atomic accessors from one thread. If another thread accesses both names at the same time, the atomic getter methods will return complete strings (without crashing), but there's no guarantee that those values will be the right names relative to each other. If the first name is accessed before the change, but the last name is accessed after the change, you'll end up with an inconsistent, mismatched pair of names.
考虑一个
XYZPerson
对象,其中一个人的名字和姓氏都使用来自一个线程的原子访问器进行了更改。如果另一个线程同时访问这两个名称,原子 getter 方法将返回完整的字符串(不会崩溃),但不能保证这些值是相对于彼此的正确名称。如果在更改之前访问了名字,而在更改之后访问了姓氏,则最终会得到不一致、不匹配的名称对。
I never had a problem using atomic at all. I designed the code that way, that there is not problem with atomic properties.
我在使用 atomic 时从来没有遇到过问题。我这样设计代码,原子属性没有问题。
回答by Robert Harvey
In answer to your third paragraph; essentially yes. An atomic number can't be read while a thread is writing the number.
回答你的第三段;基本上是的。在线程写入数字时无法读取原子序数。
For example, if a thread has written the first two bytes of an atomic four byte number, and a read of that number is requested on another thread, that read has to wait until all four bytes have been written.
例如,如果一个线程写入了原子四字节数的前两个字节,并且在另一个线程上请求读取该数字,则该读取必须等到所有四个字节都已写入。
Conversely, if a thread has written the first two bytes of a non-atomic four byte number, and a read of that number is requested on another thread at that moment, it will read the first two new data bytes, but will get old data from a previous write operation in the other two bytes.
相反,如果一个线程已经写入了一个非原子四字节数字的前两个字节,并且此时另一个线程请求读取该数字,它将读取前两个新数据字节,但会获取旧数据来自其他两个字节的先前写操作。
回答by Catfish_Man
Robert Harvey's answer is correct, but there is a sub-case of that to consider that people often miss. Consider this code: http://pastebin.com/S7XyJm6G
罗伯特哈维的回答是正确的,但有一个子案例需要考虑人们经常错过。考虑这个代码:http: //pastebin.com/S7XyJm6G
As well as preventing you from reading partially written values, atomic properties also prevent you from getting objects back that you don't control the lifetime of (they do this by retaining and then autoreleasing the object). This is important in single threaded code like the example that I linked, but even more important in multithreaded code where another thread could cause the object to be released out from under you.
除了阻止您读取部分写入的值外,原子属性还阻止您取回您无法控制其生命周期的对象(它们通过保留然后自动释放对象来实现此目的)。这在像我链接的示例这样的单线程代码中很重要,但在多线程代码中更重要,其中另一个线程可能会导致对象从您的下方释放出来。
回答by Shashi3456643
In concurrent programing:
在并发编程中:
atomic means if a property value being accessed for writing operation in some thread(thread # 1) and other thread(thread # 2) tries to access the atomic value either for read or write operation then other thread(thread # 2) waits until thread # 1 completes its task. In other words atomic synchronize the access of property on first come first serve basis.
原子意味着如果某个线程(线程#1)和其他线程(线程#2)中的写入操作访问的属性值尝试访问原子值以进行读取或写入操作,则其他线程(线程#2)等待直到线程#1 完成它的任务。换句话说,原子以先到先得的方式同步属性的访问。
non atomic means if a property value being accessed for writing operation in some thread(thread # 1) and other thread(thread # 2) tries to access the non atomic value either for read or write operation then other thread(thread # 2) gets value immediately gets old value
非原子意味着如果某个线程(线程#1)和其他线程(线程#2)中为写入操作访问的属性值尝试访问非原子值以进行读取或写入操作,则其他线程(线程#2)将获得value 立即获得旧值
回答by Suraj K Thomas
Explicit implementation of
显式实现
@property (atomic, retain) NSNumber *count
@property (atomic, retain) NSNumber *count
would be like this
会是这样
- (NSNumber *)count {
NSNumber *count;
@synchronized(self) {
count = [_count retain]; // +1
}
return [count autorelease]; // delayed -1
}
- (void)setCount:(NSNumber *)count {
id oldValue;
@synchronized(self) {
oldValue = _count;
_count = [count retain];
}
[oldValue release];
}
Atomic is the default behaviour for a property.An atomic property adds a level of thread safety when getting or setting values. That is, the getter and setter for the property will always be fully completed regardless of what other threads are doing. these properties will be a little slower to access than a nonatomic equivalent.
原子是属性的默认行为。原子属性在获取或设置值时增加了线程安全级别。也就是说,无论其他线程在做什么,属性的 getter 和 setter 将始终完全完成。这些属性的访问速度会比非原子等价物慢一点。
And explicitly we would implement
并且明确地我们将实施
@property (nonatomic, retain) NSNumber *count
@property (nonatomic, retain) NSNumber *count
like this
像这样
- (NSNumber *)count {
return _count;
}
- (void)setCount:(NSNumber *)count {
if (count != _count) {
id oldValue = _count;
_count = [count retain];
[_oldValue release];
}
}
Nonatomic properties are not thread safe, and will return their properties directly. This will be faster than atomic properties, but obviously carries some risk if precautions aren't made.
非原子属性不是线程安全的,会直接返回它们的属性。这将比原子属性更快,但如果不采取预防措施,显然会带来一些风险。
setter & getter for these Nonatomic property
这些非原子属性的 setter 和 getter