Cocoa/Objective C:方法和线程安全

Posted

技术标签:

【中文标题】Cocoa/Objective C:方法和线程安全【英文标题】:Cocoa/Objective C: methods and thread safety 【发布时间】:2011-08-26 18:39:55 【问题描述】:

在 Cocoa/Objective C 中,静态类方法是线程安全的吗?我正在定义一个类来发出相关的自定义 URL 请求,我想从许多不同的线程中调用它。假设我有一堂课:

@interface URLConnector : NSObject 

+(Response *)getData:(NSString *)category;
+(Response *)put:(NSString *)category content:(NSData *)content;
@end

每个方法定义一个 NSMutableURLRequest,调用它,并使用 NSRunLoop:runUntilDate: 来等待响应。他们还创建另一个类 URLConnectorDelegate 的实例来处理来自 NSMutableRequests 的回调,并在返回之前释放它们。 (注意:此代码基于用于发出 URL 请求的流行公共库)

我喜欢这种方法的地方在于,它使所有线程保持简单,并将所有与服务器相关的自定义代码放在一个地方。线程可以通过单个函数调用来执行 URL 请求。

我的所有线程都可以同时使用这些静态函数来进行同时调用吗(即静态 Objective-c 方法本质上是线程安全的)?

【问题讨论】:

【参考方案1】:

作为一个类方法对线程安全没有任何影响。重要的是您如何访问数据。如果您以非线程安全的方式访问数据,则该方法不是线程安全的。

而不是抽自己的运行循环,我只是将NSURLConnection 附加到主运行循环,并且 URL 加载系统按照设计的方式自行管理。见NSURLConnection scheduleInRunLoop:forMode:

【讨论】:

我编辑了这个问题,提供了更多关于我为什么要使用这种方法的信息,尽管我同意你的观点。我在网上对这个主题进行了一些研究,有些人报告说以这种方式成功运行了他们自己的运行循环,但可能会遇到与 NSURLConnection 本身相关的问题。【参考方案2】:

如果您知道您将在后台线程上,为什么不直接使用+[NSURLConnection sendSynchronousRequest:returningResponse:error:] 并完成它呢?

不需要运行循环。如果你只使用局部变量和参数,你几乎不需要任何工作就能获得线程安全。

否则线程安全取决于您的方法类型。

类方法并不比实例方法更安全。这两种方法实际上在运行时都是一样的。该类实际上是它的元类的一个对象实例,因此对类方法的调用是对对象的普通方法调用。

【讨论】:

那么,就局部变量而言,这两种方法都是线程安全的吗?例如,如果我在方法中迭代一个局部变量 - for(int i=0; i @Colin:堆栈上的任何局部变量都是线程局部的,因此是安全的。因此,只要您不使用标记为 static 的变量,或者以任何其他方式在方法范围之外保持活动状态,您就是安全的。【参考方案3】:

我看不出有任何方法可以在类方法中完成所有处理,而无需使用可能被各种线程踩踏的实例变量。我认为您需要使这些方法成为普通的实例方法并为每个线程分配一个实例。我不确定你为什么会首先考虑将它们设为类方法。

【讨论】:

我应该包括每次调用它们时,静态方法都会创建一个新的连接委托对象来处理响应。我将编辑原始帖子。【参考方案4】:

假设您正在为当前线程的运行循环调用NSRunLoop:runUntilDate:(即,无论哪个线程调用您的类方法),如果这些类方法中没有修改全局/静态变量,我相信它们应该是线程安全的。

【讨论】:

以上是关于Cocoa/Objective C:方法和线程安全的主要内容,如果未能解决你的问题,请参考以下文章

Cocoa/Objective-C 和分布式对象的例子?

Objective-C/Cocoa 中 Java 的 Thread.sleep() 等价物是啥?

使用偏移量缩放 vImage_Buffer - Cocoa Objective C

使用 vImageScale_ARGB8888 缩放图像时图像质量受到影响 - Cocoa Objective C

在 Cocoa/Objective-C 中请求热键

Cocoa/Objective-C - 带有文本输入的子窗口,而主窗口没有变为非活动状态