When can I not use atomic properties? [duplicate]

时间:2021-12-12 12:47:07

This question already has an answer here:

这个问题在这里已有答案:

I know there are answers on atomic vs. non-atomic answers, but they mostly seem to be fairly old (2011 and earlier), so I'm hoping for updated advice. My understanding is that non-atomic properties are faster but not thread safe. Does this mean that any property that might be accessed from multiple threads at the same time should always be atomic? Are there conditions that can make it ok to make it non-atomic? What other concerns are there in determining whether to make a property atomic or nonatomic?

我知道原子与非原子答案有答案,但它们似乎相当陈旧(2011年及更早),所以我希望得到更新的建议。我的理解是非原子属性更快但不是线程安全的。这是否意味着可能同时从多个线程访问的任何属性应该始终是原子的?是否存在可以使其成为非原子的条件?在确定是否将属性设为原子或非原子时还有哪些其他问题?

4 个解决方案

#1


5  

Declaring a property atomic makes compiler generate additional code that prevents concurrent access to the property. This additional code locks a semaphore, then gets or sets the property, and then unlock the semaphore. Compared to setting or getting a primitive value or a pointer, locking and unlocking a semaphore is expensive (although it is usually negligible if you consider the overall flow of your app).

声明属性atomic会使编译器生成其他代码,以防止对属性进行并发访问。此附加代码锁定信号量,然后获取或设置属性,然后解锁信号量。与设置或获取原始值或指针相比,锁定和解锁信号量是昂贵的(尽管如果考虑应用程序的整体流量,通常可以忽略不计)。

Since most of your classes under iOS, especially the ones related to UI, will be used in a single-threaded environment, it is safe to drop atomic (i.e. write nonatomic, because properties are atomic by default), even though the operation is relatively inexpensive, you do not want to pay for things that you do not need.

由于iOS下的大多数类,特别是与UI相关的类,将在单线程环境中使用,因此删除原子是安全的(即写入非原子,因为默认情况下属性是原子的),即使操作是相对的价格便宜,你不想为你不需要的东西买单。

#2


1  

Declaring a property as atomic does not necessarily make it thread safe.

将属性声明为原子并不一定使其成为线程安全的。

Atomic is the default and involves some extra overhead compared to nonatomic. If thread A is halfway through the getter for that property and thread B changes the value in the setter, using atomic will ensure that a viable, whole value is returned from the getter. If you use nonatomic no such guarantee is made, the extra code is not generated, and thus nonatomic is faster.

原子是默认值,与非原子相比需要一些额外的开销。如果线程A在该属性的getter中途,并且线程B更改了setter中的值,则使用atomic将确保从getter返回可行的整个值。如果您使用非原子,则不会产生此类保证,则不会生成额外的代码,因此非原子性更快。

However, This does not guarantee thread safety. If thread A calls the getter and threads B and C are updating the thread with different values then thread A could get either value and there is no guarantee which one it will get.

但是,这并不能保证线程安全。如果线程A调用getter并且线程B和C正在使用不同的值更新线程,则线程A可以获得任一值,并且无法保证它将获得哪一个。

To specifically answer your question, many scenarios allow for nonatomic properties, if not most. Although the extra overhead of using atomic is probably negligable. Simply put, are your properties read or set on different threads? If not, you most likely don't need to declare them as atomic but the extra overhead might not even be noticable. It's just that simply declaring them as atomic does not guarantee thread safety.

要专门回答您的问题,许多情况允许非原子属性,如果不是大多数。虽然使用原子的额外开销可能是可以忽略不计的。简单地说,您的属性是在不同的线程上读取还是设置?如果没有,你很可能不需要将它们声明为原子,但额外的开销可能甚至不是显而易见的。只是简单地将它们声明为原子并不能保证线程安全。

#3


1  

In most situations it is unimportant, whether a property is atomic or not in a multithreaded environment.

在大多数情况下,在多线程环境中属性是否为原子属性并不重要。

What?

In most situations it is unimportant, whether a property is atomic or not in a multithreaded environment.

在大多数情况下,在多线程环境中属性是否为原子属性并不重要。

The reason for this is that making a property "thread-safe" by turning atomicity on does not make your code thread-safe. To get this you need more work and this work typically implicitly ensures that the property is not accessed parallel.

这样做的原因是通过打开原子性使属性“线程安全”不会使您的代码线程安全。要实现这一点,您需要更多的工作,这项工作通常隐式确保不会并行访问该属性。

Let's have an example: You have a class Person with the properties firstName and lastName both of NSString*. You simply want to add the both name separated with a space to have a full name.

让我们举个例子:你有一个Person类,其属性firstName和lastName都是NSString *。您只想添加用空格分隔的两个名称以使用全名。

NSString *fullName = [NSString stringWithFormat:@"%@ %@", person.firstName, person.lastName];

You know that other threads can update the properties while you do that. Making the properties atomic doesn't help anything. This does not help, if the last name of the persons are changed, after reading the first name, but before reading the second name. This does not help, if the names of the persons are changed after calculating the full name, because this can be invalid in the very next moment.

您知道其他线程可以在您执行此操作时更新属性。使属性原子化没有任何帮助。如果在读取第一个名称之后,但在读取第二个名称之前更改了人员的姓氏,这没有任何帮助。如果在计算全名后更改了人员的姓名,这没有用,因为这可能在下一刻无效。

You have to serialize operations, not property accesses. But atomicity only serializes accesses. So it does not help, if at least one operation has more than one access. 99,999999373 % of all cases.

您必须序列化操作,而不是属性访问。但原子性只能序列化访问。因此,如果至少一个操作具有多个访问权限,则无效。所有案件的99,999999373%。

Forget about property atomicity. It is meaningless.

忘记属性原子性。这毫无意义。

#4


-1  

There are no other concerns. Yes, any property that can be accessed on multiple threads should be atomic or you can end up with unexpected results.

没有其他问题。是的,任何可以在多个线程*问的属性都应该是原子的,否则最终会出现意外结果。

#1


5  

Declaring a property atomic makes compiler generate additional code that prevents concurrent access to the property. This additional code locks a semaphore, then gets or sets the property, and then unlock the semaphore. Compared to setting or getting a primitive value or a pointer, locking and unlocking a semaphore is expensive (although it is usually negligible if you consider the overall flow of your app).

声明属性atomic会使编译器生成其他代码,以防止对属性进行并发访问。此附加代码锁定信号量,然后获取或设置属性,然后解锁信号量。与设置或获取原始值或指针相比,锁定和解锁信号量是昂贵的(尽管如果考虑应用程序的整体流量,通常可以忽略不计)。

Since most of your classes under iOS, especially the ones related to UI, will be used in a single-threaded environment, it is safe to drop atomic (i.e. write nonatomic, because properties are atomic by default), even though the operation is relatively inexpensive, you do not want to pay for things that you do not need.

由于iOS下的大多数类,特别是与UI相关的类,将在单线程环境中使用,因此删除原子是安全的(即写入非原子,因为默认情况下属性是原子的),即使操作是相对的价格便宜,你不想为你不需要的东西买单。

#2


1  

Declaring a property as atomic does not necessarily make it thread safe.

将属性声明为原子并不一定使其成为线程安全的。

Atomic is the default and involves some extra overhead compared to nonatomic. If thread A is halfway through the getter for that property and thread B changes the value in the setter, using atomic will ensure that a viable, whole value is returned from the getter. If you use nonatomic no such guarantee is made, the extra code is not generated, and thus nonatomic is faster.

原子是默认值,与非原子相比需要一些额外的开销。如果线程A在该属性的getter中途,并且线程B更改了setter中的值,则使用atomic将确保从getter返回可行的整个值。如果您使用非原子,则不会产生此类保证,则不会生成额外的代码,因此非原子性更快。

However, This does not guarantee thread safety. If thread A calls the getter and threads B and C are updating the thread with different values then thread A could get either value and there is no guarantee which one it will get.

但是,这并不能保证线程安全。如果线程A调用getter并且线程B和C正在使用不同的值更新线程,则线程A可以获得任一值,并且无法保证它将获得哪一个。

To specifically answer your question, many scenarios allow for nonatomic properties, if not most. Although the extra overhead of using atomic is probably negligable. Simply put, are your properties read or set on different threads? If not, you most likely don't need to declare them as atomic but the extra overhead might not even be noticable. It's just that simply declaring them as atomic does not guarantee thread safety.

要专门回答您的问题,许多情况允许非原子属性,如果不是大多数。虽然使用原子的额外开销可能是可以忽略不计的。简单地说,您的属性是在不同的线程上读取还是设置?如果没有,你很可能不需要将它们声明为原子,但额外的开销可能甚至不是显而易见的。只是简单地将它们声明为原子并不能保证线程安全。

#3


1  

In most situations it is unimportant, whether a property is atomic or not in a multithreaded environment.

在大多数情况下,在多线程环境中属性是否为原子属性并不重要。

What?

In most situations it is unimportant, whether a property is atomic or not in a multithreaded environment.

在大多数情况下,在多线程环境中属性是否为原子属性并不重要。

The reason for this is that making a property "thread-safe" by turning atomicity on does not make your code thread-safe. To get this you need more work and this work typically implicitly ensures that the property is not accessed parallel.

这样做的原因是通过打开原子性使属性“线程安全”不会使您的代码线程安全。要实现这一点,您需要更多的工作,这项工作通常隐式确保不会并行访问该属性。

Let's have an example: You have a class Person with the properties firstName and lastName both of NSString*. You simply want to add the both name separated with a space to have a full name.

让我们举个例子:你有一个Person类,其属性firstName和lastName都是NSString *。您只想添加用空格分隔的两个名称以使用全名。

NSString *fullName = [NSString stringWithFormat:@"%@ %@", person.firstName, person.lastName];

You know that other threads can update the properties while you do that. Making the properties atomic doesn't help anything. This does not help, if the last name of the persons are changed, after reading the first name, but before reading the second name. This does not help, if the names of the persons are changed after calculating the full name, because this can be invalid in the very next moment.

您知道其他线程可以在您执行此操作时更新属性。使属性原子化没有任何帮助。如果在读取第一个名称之后,但在读取第二个名称之前更改了人员的姓氏,这没有任何帮助。如果在计算全名后更改了人员的姓名,这没有用,因为这可能在下一刻无效。

You have to serialize operations, not property accesses. But atomicity only serializes accesses. So it does not help, if at least one operation has more than one access. 99,999999373 % of all cases.

您必须序列化操作,而不是属性访问。但原子性只能序列化访问。因此,如果至少一个操作具有多个访问权限,则无效。所有案件的99,999999373%。

Forget about property atomicity. It is meaningless.

忘记属性原子性。这毫无意义。

#4


-1  

There are no other concerns. Yes, any property that can be accessed on multiple threads should be atomic or you can end up with unexpected results.

没有其他问题。是的,任何可以在多个线程*问的属性都应该是原子的,否则最终会出现意外结果。