返回
多线程情境中 CFRunloop 安全吗?
IOS
2023-10-10 04:32:46
很多人在讨论CFRunloop时,都会强调它的线程安全特性。然而,事情往往并没有那么简单。CFRunloop在多线程环境中,尤其是在停止runloop时,存在着安全隐患。虽然苹果官方也承认了这一点,但他们仅仅用了一个模糊的词语“generally”来这种不安全性。
/*
* Copyright (c) 2009-2019 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Software License Terms.
*
* @APPLE_LICENSE_HEADER_END@
*/
/* Block until the specified run loop exits.
* Only guaranteed to work for the current run loop, or the run loop of a thread
* that is calling CFRunLoopRun, and generally only if no other threads are
* modifying the run loop state (adding/removing sources or observers).
*/
CF_EXPORT
void CFRunLoopWait(CFRunLoopRef rl, CFTimeInterval seconds);
在实际编程中,CFRunloop多线程隐患主要是出现在停止runloop时,因为此时runloop的状态是可能会被其他线程修改的。举个例子,假设我们有一个线程A负责管理runloop,而线程B负责向runloop中添加新的source。当线程A调用CFRunLoopStop时,线程B可能刚好也在向runloop中添加source,这就会导致runloop的状态发生变化,从而引发安全问题。
为了避免这种安全隐患,我们可以使用如下几种解决方案:
- 使用互斥锁来保护runloop的状态。在停止runloop之前,先获得互斥锁,然后停止runloop,最后释放互斥锁。这样就可以确保在停止runloop时,不会有其他线程对runloop的状态进行修改。
- 使用CFRunLoopPerformBlock函数来停止runloop。CFRunLoopPerformBlock函数会在runloop的下一个循环中执行指定的block,因此我们可以使用这个函数来安全地停止runloop。
- 使用CFRunLoopRunInMode函数来停止runloop。CFRunLoopRunInMode函数会一直运行runloop,直到指定的mode结束,因此我们可以使用这个函数来安全地停止runloop。
总之,虽然CFRunloop是线程安全的,但在多线程环境中停止runloop时,存在着安全隐患。我们可以使用互斥锁、CFRunLoopPerformBlock函数或CFRunLoopRunInMode函数来避免这种安全隐患。