Objective c 这些局部变量如何避免竞争条件?
我遇到了这样一段代码:Objective c 这些局部变量如何避免竞争条件?,objective-c,multithreading,race-condition,Objective C,Multithreading,Race Condition,我遇到了这样一段代码: id target = self.target; SEL selector = self.selector; if([target respondToSelector:@SEL(selector)]) { [target performSelector:@SEL(selector)]; } 作者给出了这样的解释: 我们创建了两个局部变量,以避免在以下可能的执行序列中出现竞争条件: 在某个线程A中调用[target respondsToSelector:selecto
id target = self.target;
SEL selector = self.selector;
if([target respondToSelector:@SEL(selector)])
{
[target performSelector:@SEL(selector)];
}
作者给出了这样的解释:
我们创建了两个局部变量,以避免在以下可能的执行序列中出现竞争条件:
[target respondsToSelector:selector]
[目标性能选择器:选择器]
我想知道的是:竞争的是哪种资源?这两个局部变量如何帮助避免竞争条件?我真的不知道比赛条件在哪里。提前谢谢 通常情况下,争用条件是多个线程同时存在的任何情况
- 争夺某些共享资源李>
- 这些线程没有同步对这些资源的访问;因此
- 结果行为取决于各个线程中事件的精确计时或顺序
if ([self.target respondToSelector:@SEL(self.selector)]) {
[self.target performSelector:@SEL(self.selector)];
}
在此实现中,在线程A确定响应选择器
成功和尝试执行选择器
之间,线程B可能已经滑入并将选择器或目标更改为其他内容。更糟糕的是,如果线程B将这些属性中的任何一个更改为无法执行的内容,应用程序可能会崩溃
通过在局部变量中复制这些引用(如原始代码片段所示),开发人员消除了这种可能性。因为在线程A中运行的这个例程有到目标和选择器引用的副本,所以现在B是否在选中响应选择器
和调用性能选择器
之间更改属性无关紧要。线程A可以安全地使用其局部变量,从而消除这种特殊的争用条件
但这并不意味着这是真正的线程安全:
- 首先,如果多个线程真的对这两个属性执行非同步访问,那么它们至少必须是原子属性。(我不会这么做,原因我将在后面介绍,但在代码段中这样做时,这是最低限度的。)
- 第二,这两个属性之间存在第二个竞争条件。假设
和self.target
分别引用一些self.selector
对象和实例方法。假设线程A获得了Foo
目标,但在它获得检索选择器的机会之前,线程B滑入并将Foo
和self.target
更改为一个完全不同的对象,比如一个self.selector
对象。然后线程A检索Bar
,它现在引用一些self.selector
实例方法。当然,如果您问题中的代码使用局部变量来保存Bar
和目标
(因为选择器
目标上的Foo
方法的Bar
可能会失败),但它也不会做您想要的事情。而这通常也同样糟糕respondsToSelector
- 在目标对象本身中,显然还有其他线程安全注意事项。例如,如果该目标对象不是线程安全的,那么线程B可能正在对目标对象进行变异的过程中,并且当线程A尝试调用选择器方法时,它可能处于内部不一致的状态。因此,您必须确认
对象本身是否是线程安全的目标
@synchronized
指令来执行此操作
而且,回到我之前关于原子属性的评论,如果您使用一些更广泛的同步模式来实现更健壮的线程安全解决方案,那么通常不需要原子属性。一般来说,争用条件是多个线程同时运行的任何情况
- 争夺某些共享资源李>
- 这些线程没有同步对这些资源的访问;因此
- 结果行为取决于各个线程中事件的精确计时或顺序