You need to enable JavaScript to run this app. DispatchQueue是否锁内部资源?跨线程访问共享资源需加锁吗?
优惠活动
大模型
产品
解决方案
定价
更多

DispatchQueue是否锁内部资源?跨线程访问共享资源需加锁吗?

DispatchQueue 对闭包内共享资源的防护逻辑说明

核心结论

DispatchQueue 不会自动锁定、防护闭包内部引用的任何共享资源。它的核心能力是按照队列预设的调度规则(串行/并行、QoS等级、线程绑定关系)执行提交的闭包任务,完全没有内置的资源访问识别、并发冲突检测逻辑。

结合示例代码的拆解

你给出的实现代码如下:

class Factory {
  var localSharedResource
  var localQueue =  DispatchQueue(label: "localQueue")
  let threadLock = NSLock()

  func modify(){
    localQueue.async {
      self.threadLock.lock() 
      localSharedResource = "a change is made here"
      self.threadLock.unlock()
    }
  }
}

针对你提出的“如果localSharedResource同时会被其他线程访问,是否还需要锁防护”的问题,可以分场景明确判断标准:

  • 如果项目中所有对localSharedResource的读、写操作,全部统一提交到这个默认创建的串行localQueue上执行,那你连threadLock都不需要加。因为无特殊配置的DispatchQueue默认是串行队列,天然保证队列内的任务不会并发执行,对资源的所有访问都是顺序完成的,不存在数据竞争风险。
  • 只要存在任意一处对localSharedResource的访问,没有被收口到这个localQueue上(比如直接在主线程读取该属性、提交到其他队列修改该值),就必须做并发防护。这种情况下你在队列闭包内部加NSLock的写法是起不到防护作用的:因为锁的生效前提是所有访问共享资源的代码路径,都先获取同一个锁实例,绕过队列的外部访问路径根本没有获取这把锁的逻辑,和队列内的写操作会形成跨线程并发,触发不可预期的数据错乱。
  • 如果你给localQueue配置了.concurrent属性,那就算所有访问都在这个队列上,也需要额外做防护,因为并行队列的任务是并发执行的,本身就不保证资源访问的顺序安全。

常见认知误区

很多开发者会误以为“把任务丢到队列里就自动线程安全了”,本质上是混淆了队列的调度能力和资源防护能力——队列只管自己队列内的任务执行规则,管不到队列外的代码对共享资源的操作,更不会自动帮你给资源加锁。

内容的提问来源于stack exchange,提问作者George Termentzoglou

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.30 10:36:08