从另一个线程调用setter时读取实例变量是否安全? [英] Is it thread-safe to read an instance variable while calling a setter from another thread?

查看:103
本文介绍了从另一个线程调用setter时读取实例变量是否安全?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个带有属性的对象:

I have an object with a property:

@interface Car
@property(strong) NSLicensePlate *licensePlate;
@end

我在一种方法中使用该属性:

I use the property in a method:

- (void) doSomething {
    [_licensePlate frobnicate];
}

并且可以通过另一种方法更改属性值:

And the property value can be changed in another method:

- (void) doSomethingElse {
    [self setLicensePlate:[_licensePlateDealer cleanLicensePlate]];
}

现在,如果在我使用实例变量访问车牌属性的同时从另一个线程调用了-doSomethingElse方法(如在-doSomething方法中所示),是否有可能出现段错误?

Now, if the -doSomethingElse method is called from another thread while I access the license plate property using the instance variable (as seen in the -doSomething method), is it possible to get a segfault?

-setLicensePlate设置器是否有可能在我调用-frobnicate之前和在分配新的有效值之前释放存储在_licensePlate中的值?调用[self licensePlate]而不是直接使用_licensePlate会有所帮助吗?

Is it possible that the -setLicensePlate setter releases the value stored in _licensePlate right before I call -frobnicate on it and before a new valid value is assigned? And would it help to call [self licensePlate] instead of using _licensePlate directly?

推荐答案

如果您想享受此的atomic行为(这是您未指定nonatomic限定符而获得的默认行为)属性,必须使用吸气剂(self.licensePlate[self licensePlate]),而不要使用ivar(_licensePlate).

If you want to enjoy the atomic behavior (which is the default behavior that you get because you didn't specify the nonatomic qualifier) of this property, you must use the getter (self.licensePlate or [self licensePlate]), not use the ivar (_licensePlate).

通常,除(a)init方法外,通常在所有地方都使用getter和setter方法是谨慎的. (b)和自定义访问器方法.开销可以忽略不计,并且避免了潜在的问题,例如原子性,内存语义,KVO,面向未来的代码,以防您在将来某个日期自定义访问器方法等.

In general, it's usually prudent to use the getters and setters everywhere except (a) the init method; and (b) and custom accessor methods. The overhead is negligible and you avoid spectrum of potential problems ranging from atomicity, memory semantics, KVO, future-proofing code in case you customize accessor methods at some future date, etc.

但是,假设您仅通过访问器方法(getter和setter)访问属性,则使用atomic限定符,如

But, assuming you access your property only through the accessor methods (the getters and setters), the atomic qualifier, as described by Programming with Objective-C: Encapsulating Data ensures that the pointer, itself, that you are retrieving/setting is will not be corrupted by another thread:

[Atomic]意味着即使访问器是从不同线程中同时调用的,综合访问器也可以确保始终通过getter方法完全检索值或通过setter方法完全设置值.

[Atomic] means that the synthesized accessors ensure that a value is always fully retrieved by the getter method or fully set via the setter method, even if the accessors are called simultaneously from different threads.

为回答您的问题,如果在另一个线程上运行frobnicate方法时,另一个线程更改了licensePlate属性,则直到该方法返回后,该原始对象才会被释放.

In answer to your question, if the other thread changes the licensePlate property, while the frobnicate method is running on the other thread, that original object will not be released until that method returns.

但是要清楚一点,atomic限定符不能不能确保线程安全.随着以上指南的继续警告我们:

But to be clear, the atomic qualifier does not ensure thread safety. As the above guide goes on to warn us:

注意:属性原子性与对象的线程安全性并不相同.

Note: Property atomicity is not synonymous with an object’s thread safety.

考虑一个XYZPerson对象,其中使用一个线程中的原子访问器来更改一个人的名字和姓氏.如果另一个线程同时访问两个名称,则原子getter方法将返回完整的字符串(不会崩溃),但不能保证这些值相对于彼此是正确的名称.如果在更改之前访问了名字,但在更改之后访问了姓氏,那么您将得到一对不一致且不匹配的名称.

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.

这个例子非常简单,但是当跨相关对象网络考虑时,线程安全性的问题变得更加复杂.线程安全性在

This example is quite simple, but the problem of thread safety becomes much more complex when considered across a network of related objects. Thread safety is covered in more detail in Concurrency Programming Guide.

因此,在一个线程上使用frobnicate,同时在另一个线程上执行其他操作,可能是线程安全的,但也可能不是.这取决于此车牌对象可以完成的所有不同操作.由于atomic提供的保护非常简单,因此我们经常会采用一些同步(通过GCD串行队列或GCD读写器模式,或者通过

So, it might be thread-safe to use frobnicate on one thread while doing other stuff on another thread, but it also might not. It depends upon all the different things that can be done with this license plate object. Because the protections offered by atomic are so minimalist, we frequently will employ some synchronization (via GCD serial queue or GCD reader-writer pattern, or via any of the synchronization methods outlined in the Threading Programming Guide: Synchronization such as locks) to coordinate interaction from different threads.

这篇关于从另一个线程调用setter时读取实例变量是否安全?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆