闭包线程安全吗?

Are closures thread safe?

假设我有一个这样的class:

class Bla {
    var callback: (() -> Void)?

    // doStuff will be called from multiple threads
    func doStuff() {
        callback?()
    }
}

从多个线程调用闭包是线程安全的吗?闭包在此期间不会被修改,只会被调用。

闭包内部是线程安全代码。

不幸的是,线程安全不是一个直截了当的问题。具体来说,虽然块的读取对于多个线程是安全的。

在 swift 中,闭包通过引用传递。当您将它分配给“var callback”时,它会在堆中接收一个内存地址。只要变量在其他线程读取访问时没有更改,该地址就可以由多个线程同时读取。即使您在块中捕获了一个变量,该变量也会被块捕获,如果它不是引用类型,甚至可以通过闭包进行修改。不过,您肯定要小心在调用站点内所做的事情。例如,如果闭包被多个线程调用并且在你内部传递了 say..

var i = 0 
callback = {
     i += 1
}


for _ in 0...100 {
      
     DispatchQueue.global().async {
            bla.closure()
    }
 }

这显然不再被认为是“线程安全的”,因为您仍在通过多个线程进行变异。例如两个或三个线程可能读取 1 并加 1,另外十二个线程可能读取 5 并在 return 上写入 6;或更糟的是,第二个线程最后完成,在 100 次调用后你有 i = 2.

此外,如果“var i”是引用类型,程序可能会因错误访问异常而崩溃。