【问题标题】:Is DispatchSemaphore a good replacement for NSLock?DispatchSemaphore 是 NSLock 的良好替代品吗?
【发布时间】:2017-04-18 09:39:06
【问题描述】:

我一直在使用NSLocks 来同步敏感的代码部分,但由于必须从锁定它们的同一线程解锁它们而遇到问题。然后我发现 GCD 的 DispatchSemaphores 似乎做同样的事情,增加了可以从任何线程发出信号的便利。不过,我想知道这种便利是否是以线程安全为代价的。是否可以更换

let lock = NSLock()
lock.lock()
// do things...
lock.unlock()

let semaphore = DispatchSemaphore(value: 1)
semaphore.wait()
// do things...
semaphore.signal()

还是我会遇到关于线程安全的问题?

【问题讨论】:

  • 仍然没有得到答案,但我更喜欢使用信号量的另一个原因是即使它们没有“锁定”,也可以安全地“解锁”它们。
  • DispatchSemaphore 有一个缺陷——它从 iOS10.0 开始可用。

标签: swift concurrency swift3


【解决方案1】:

是的,它们具有相同的功能,都用于处理生产者-消费者问题。

如果相应配置,信号量允许多个线程访问共享资源。您可以在同一个并发dispatchQueue中执行块。

{
    semaphore.wait()
    // do things...
    semaphore.signal()
}

实际上这同样适用于 Lock,如果您只希望一个线程以并发方式一次接触资源。

我发现这很有帮助:https://priteshrnandgaonkar.github.io/concurrency-with-swift-3/

【讨论】:

    【解决方案2】:

    自从提出这个问题后,我主要转向了另一种锁定代码块的方式:串行调度队列。我是这样使用的:

    let queue = DispatchQueue(label: "<your label here>")
    queue.async {
        // do things...
    }
    

    默认情况下,队列是串行的,这意味着它充当锁,在退出块时释放。因此,如果您需要锁定异步操作,这是不合适的,但它在大多数情况下都很有效。

    【讨论】:

    • 您还可以在需要时将其与屏障同步一起使用来锁定(即写入可以阻止读取直到它们完成)。 raywenderlich.com/…中的好例子
    • 不要这样做。完全没有必要。单个信号量的开销要少得多。您创建的队列 1) 不需要 2) 每次调度时创建堆栈帧 3) 捕获上下文。
    • @ErikAigner 我将创建一个队列以将工作移出主队列,并创建一个信号量以在异步工作完成时阻塞队列。
    • @ErikAigner 在许多情况下,性能差异是微不足道的。在过多担心这一点之前,您应该对代码进行基准测试以了解它对性能的敏感程度。过早的优化是万恶之源。
    猜你喜欢
    • 2018-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-01
    • 1970-01-01
    相关资源
    最近更新 更多