ARC 是不是支持调度队列?

Posted

技术标签:

【中文标题】ARC 是不是支持调度队列?【英文标题】:Does ARC support dispatch queues?ARC 是否支持调度队列? 【发布时间】:2012-01-26 23:10:31 【问题描述】:

我正在阅读苹果关于“调度队列的内存管理”的文档:

即使您实现了一个垃圾收集应用程序,您仍然必须保留和释放您的调度队列和其他调度对象。 Grand Central Dispatch 不支持用于回收内存的垃圾收集模型。

我知道 ARC 不是垃圾收集器,但我想确定我不需要 dispatch_retain 和 dispatch_release 我的 dispatch_queue_t

【问题讨论】:

【参考方案1】:

简短的回答:是的,ARC 保留和释放调度队列。

现在是长答案……

如果您的部署目标低于 ios 6.0 或 Mac OS X 10.8

您需要在队列中使用dispatch_retaindispatch_release。 ARC 不管理它们。

如果您的部署目标是 iOS 6.0 或 Mac OS X 10.8 或更高版本

ARC 将为您管理您的队列。如果启用了 ARC,则不需要(也不能)使用 dispatch_retaindispatch_release

详情

从 iOS 6.0 SDK 和 Mac OS X 10.8 SDK 开始,每个调度对象(包括 dispatch_queue_t)也是一个 Objective-C 对象。这记录在 <os/object.h> 头文件中:

 * By default, libSystem objects such as GCD and XPC objects are declared as
 * Objective-C types when building with an Objective-C compiler. This allows
 * them to participate in ARC, in RR management by the Blocks runtime and in
 * leaks checking by the static analyzer, and enables them to be added to Cocoa
 * collections.
 *
 * NOTE: this requires explicit cancellation of dispatch sources and xpc
 *       connections whose handler blocks capture the source/connection object,
 *       resp. ensuring that such captures do not form retain cycles (e.g. by
 *       declaring the source as __weak).
 *
 * To opt-out of this default behavior, add -DOS_OBJECT_USE_OBJC=0 to your
 * compiler flags.
 *
 * This mode requires a platform with the modern Objective-C runtime, the
 * Objective-C GC compiler option to be disabled, and at least a Mac OS X 10.8
 * or iOS 6.0 deployment target.

这意味着您可以将队列存储在NSArrayNSDictionary 中,或者存储在具有strongweakunsafe_unretainedassignretain 属性之一的属性中。这也意味着如果你从一个块中引用你的队列,该块将自动保留队列。

所以如果您的部署目标至少是 iOS 6.0 或 Mac OS X 10.8,并且您启用了 ARC,ARC 将保留和释放您的队列,并且编译器会将任何使用dispatch_retaindispatch_release 的尝试标记为错误。

如果您的部署目标至少是 iOS 6.0 或 Mac OS X 10.8,并且您已禁用 ARC,您必须手动保留和释放您的队列,要么调用dispatch_retaindispatch_release通过发送队列retainrelease消息(如[queue retain][queue release])。

为了与旧代码库兼容,您可以通过将OS_OBJECT_USE_OBJC 定义为0 来防止编译器将您的队列视为Objective-C 对象。例如,您可以将其放在您的 .pch 文件中(在任何 #import 语句之前):

#define OS_OBJECT_USE_OBJC 0

或者您可以在构建设置中添加OS_OBJECT_USE_OBJC=0 作为预处理器宏。如果您将OS_OBJECT_USE_OBJC 设置为0,ARC 将不会为您保留或释放您的队列,您必须自己使用dispatch_retaindispatch_release 来完成。

【讨论】:

但是请注意,新的更改将调度对象指定为 Objective-C 对象。因此,即使 ARC 被禁用,如果被块捕获,这些对象也会自动保留——就像所有其他 Objective-C 对象一样。 有一个有趣的边缘案例。如果您的库部署到 iOS 5.1 并且您的应用程序部署到 6.0 并且您正在使用 ARC,您需要在 5.1 dealloc 代码中 dispatch_release NULL 对象。否则,某些东西(编译器生成的代码?运行时本身?)会再次尝试释放对象。 在使用 Mac OS 10.7 时是否需要调度我创建的其他源对象? 您必须在 OS X 10.7 下手动保留/释放所有 GCD 对象。【参考方案2】:

这里只是跟进...如果您的最低部署目标是 iOS 6,ARC 现在可以管理它们。

【讨论】:

这也适用于山狮。如果您的部署目标是 iOS 6 或 Mountain Lion,则不能(默认)使用 dispatch_release,因为这是一个宏,它会向对象发送发布消息,而 ARC 不允许这样做。

以上是关于ARC 是不是支持调度队列?的主要内容,如果未能解决你的问题,请参考以下文章

linux内核—进程调度(核心)

获取当前调度队列?

[YARN-1963] 支持同一个队列内作业按优先级调度

Hadoop-yarn组件的三种调度器

干货!来取!Hadoop调度器 和Hive中发生数据倾斜的处理方法

YARN公平调度器-原理和入门配置