这两个点之间可能存在竞争条件。想象一下,如果您doSomething()
在 2 个单独的线程上执行该函数,如下所示:
- 第一个线程执行
increaseWork()
闭包并完成它。现在排队等候
- 第二个线程开始执行并命中异步执行指令
- 第一个线程命中返回指令,等待可以继续
- 同时,从秒开始的闭包被调度并执行
此时,您无法确定首先执行的是什么:sum = sum + 100
来自第二个线程还是return sum
来自第一个线程。
这个想法是这sum
是一个不同步的共享资源,所以,理论上,这可能是一个竞争条件。即使您注意不要发生这种情况,Thread Sanitizer 也会检测到可能的竞争条件,因为它不知道您是启动单个线程还是doSomething()
同时从 100 个不同的线程执行函数。
更新:
由于我错过了变量是本地的这一事实,sum
因此上述解释并未回答当前问题。所描述的场景永远不会在给定的代码中发生。
但是,即使sum
是一个局部变量,由于它在闭包中使用和保留,它将被分配在堆上,而不是在堆栈上。这是因为 Swift 编译器无法确定闭包是否会在doSomething()
函数返回之前完成执行。
为什么?因为闭包被传递给行为类似于@escaping
参数的构造函数。这意味着无法保证何时执行闭包,因此闭包保留的所有变量都必须在堆上分配以确保安全。不知道何时执行闭包,Thread Sanitizer 无法确定return sum
闭包完成后该语句是否确实会执行。
因此,即使在这里我们可以确定不会发生竞争条件,Thread Sanitizer 也会发出警报,因为它无法确定它不会发生。