分配一个 NSThread 然后多次 initWithTarget 线程是不是安全?

Posted

技术标签:

【中文标题】分配一个 NSThread 然后多次 initWithTarget 线程是不是安全?【英文标题】:Is it safe to alloc a NSThread and then initWithTarget the thread multiple times?分配一个 NSThread 然后多次 initWithTarget 线程是否安全? 【发布时间】:2011-11-17 03:48:55 【问题描述】:

我有一个 Quartz Composer 的自定义补丁,它是一个多播接收器。它为守护进程启动一个 NSThread,然后在用户更改多播地址或端口号时重新启动它。

当补丁启动时,我会执行以下操作来启动一个新线程。

daemonThread = [NSThread alloc];

然后,每次我启动或重新启动线程时,我都会重新初始化它:

[daemonThread initWithTarget:multicastDaemon selector:@selector(doWorkWithDelegate:) object:self];
[daemonThread start];

当然,我每次在重新启动线程之前都会终止它。我没有使用垃圾收集,当补丁退出时我确实释放了 daemonThread。

我担心的是,当我像这样一遍又一遍地重新初始化这个线程时,我不确定会发生什么。我注意到 Instruments 告诉我我正在泄漏一个 NSThread 和一个 autoreleasepool,我怀疑这可能是我来自守护线程的池。我可以看到每次我重新启动该过程时这些数字都会增加,但我对 Instruments 不够熟悉,不知道它告诉我什么。

我应该担心吗?

【问题讨论】:

【参考方案1】:

在任何已经初始化的对象上调用任何init... 方法都是不安全的。这包括 NSThread。

【讨论】:

如果线程退出了怎么办?我这样做是为了让线程有一个带有 didFinish 类型方法的委托,该方法在 usleep 然后退出之前被调用。该方法通过 ivar 设置一个标志,表示线程已死。然后,下一帧看到该帧已死,并像您在上面看到的那样初始化一个 daemonThread。那安全吗?我知道 NSThread 无法重新启动,这就是我最终这样做的原因。如果不安全,还有什么安全的替代方案? @Adam 在单个对象上多次调用初始化程序是不安全的。期间。 安全的替代方法是分配一个新的 NSThread。你不知道 NSThread 可能在幕后分配了哪些资源,它只在dealloc 中发布,因此如果你初始化它两次就会泄漏。如果你正在使用它,你也可能会搞砸 ARC。 "It is undefined behavior for a program to cause two or more calls to init methods on the same object, except that each init method invocation may perform at most one delegate init call." 感谢您的帮助!我已经把 daemonThread 从一个 ivar 变成了一个局部变量。我创建了一个新的局部变量来指向 daemonThread,这样我仍然可以引用他来释放他。这摆脱了 NSThread 泄漏。然后,我仍然有 nsautoreleasepool 泄漏。我注意到我在 daemonThread 中的 [NSThread exit] 在我的自动释放池中,所以我将它移到池外。做到了。没有更多的泄漏!

以上是关于分配一个 NSThread 然后多次 initWithTarget 线程是不是安全?的主要内容,如果未能解决你的问题,请参考以下文章

目标 C - NSthread 和 NSAutoreleasePool?

带有 _NSAutoreleaseNoPool 错误的 NSThread

什么时候释放 NSThread 是安全的?

九使用多线程——NSThread,GCD和NSOperation

16iOS多线程篇:NSThread

iOS多线程篇:NSThread