【问题标题】:Racing condition on a custom concurrent queue sync for getter and settergetter 和 setter 的自定义并发队列同步的竞赛条件
【发布时间】:2017-10-02 03:42:20
【问题描述】:

我有以下代码,据我了解,它应该在_predictions 上提供线程安全读写。我的isolationQueue 是一个并发队列,需要保持不变。我在这个队列上调用多个独立的异步操作来计算各种图像的预测。各种调用之间唯一共享的项目是设置预测的时间。

  var isolationQueue = DispatchQueue.global(qos: .default)
  var _predictions: [Int:[Prediction]] = [:]

  var predictions:[Int: [Prediction]] {
    get {
      var result: [Int: [Prediction]]!
      isolationQueue.sync {
        result = _predictions
      }
      return result
    }
    set(value) {
      isolationQueue.sync {
        self._predictions = value
      }
    }
  }

但是由于某种原因,Thread Sanitizer 似乎检测到 getter 和 setter 之间的竞争情况。

我错过了什么吗?

【问题讨论】:

  • isolationQueue 是如何定义的?它是 serial 调度队列吗?
  • 更新了问题。它是全球性的,因此我相信它会同时发生。 var isolationQueue = DispatchQueue.global(qos: .default)

标签: ios swift grand-central-dispatch swift4


【解决方案1】:

全局调度队列是并发队列,所以它们不能是 用于防止对资源的并发访问。

您应该为此目的定义自己的 serial 调度队列:

var isolationQueue = DispatchQueue(label: "my.queue.identifier") 

【讨论】:

  • 使用sync 不能防止其他线程在并发队列中执行资源时访问资源?有没有办法确保并发队列上的串行访问?
  • @RezaShirazian:sync 表示调用线程等待完成,但从不同线程调度的块可以同时执行。以下是 4 种可能组合的简要概述:stackoverflow.com/questions/19179358/…
  • 那我该怎么处理sync?如果我的isolationQueue 是串行的sync 在这种情况下似乎没有多大意义。
  • @RezaShirazian: isolationQueue.async { ... } 会立即返回,无需等待项目被执行。同步/异步和串行/并发是独立的参数。看看stackoverflow.com/a/19179791/1187415 并尝试一下! – (您可以在 setter 上使用 async,但不能在 getter 方法上使用。)
  • 谢谢马丁。我想我想通了。一方面,我的队列需要保持并发,因为我需要运行多个独立的异步操作来计算预测。将我的 setter 设置为 async(flags: .barrier) 可确保当我设置预测字典时,此队列上的其他操作不会修改它。
【解决方案2】:

对于您的情况,使用 DispatchSemaphore() 更简单,开销也更少。代码看起来像

var isolationSem = DispatchSemaphore(value: 1)
var _predictions: [Int:[Prediction]] = [:]

var predictions:[Int: [Prediction]] {
  get {
    var result: [Int: [Prediction]]!
    isolationSem.wait()
    result = _predictions
    isolationSem.signal()
    return result
  }
  set(value) {
    isolationSem.wait()
    self._predictions = value
    isolationSem.signal()
  }
}

DispatchSemaphore 不适用的情况见this

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-29
    • 1970-01-01
    • 2017-10-31
    • 1970-01-01
    相关资源
    最近更新 更多