快速

时间:2017-09-12 06:36:48

标签: ios swift swift3 concurrency mutual-exclusion

我有多个线程之间的共享内存。我想阻止这些线程同时访问这段内存。 (比如 producer-consumer 问题)

问题

线程向队列添加元素,另一个线程读取这些元素并删除它们。他们不应该同时访问队列。

此问题的一个解决方案是使用Mutex。

正如我发现的那样,Swift中没有Mutex。 Swift还有其他选择吗?

3 个答案:

答案 0 :(得分:6)

有很多解决方案,但我使用串行队列进行此类操作:

let serialQueue = DispatchQueue(label: "queuename")
serialQueue.sync { 
 //call some code here, I pass here a closure from a method
}

编辑/更新:也适用于信号量:

let higherPriority = DispatchQueue.global(qos: .userInitiated)
        let lowerPriority = DispatchQueue.global(qos: .utility)

        let semaphore = DispatchSemaphore(value: 1)

        func letUsPrint(queue: DispatchQueue, symbol: String) {
            queue.async {
                debugPrint("\(symbol) -- waiting")
                self.semaphore.wait()  // requesting the resource

                for i in 0...10 {
                    print(symbol, i)
                }

                debugPrint("\(symbol) -- signal")
                self.semaphore.signal() // releasing the resource
            }
        }

        letUsPrint(queue: higherPriority, symbol: "High Priority Queue Work")
        letUsPrint(queue: lowerPriority, symbol: "Low Priority Queue Work")

答案 1 :(得分:5)

感谢beshio的评论,您可以像这样使用信号量:

let semaphore = DispatchSemaphore(value: 1)

在使用资源之前使用wait:

semaphore.wait()
// use the resource

并在使用后释放:

semaphore.signal()

在每个帖子中执行此操作。

答案 2 :(得分:3)

正如人们评论(包括我),有几种方法可以实现这种锁定。但我认为调度信号量比其他信号量更好,因为它似乎具有最小的开销。如Apples doc, "Replacing Semaphore Code"中所见,除非信号量已被锁定(= 0),否则它不会进入内核空间,这是代码进入内核切换线程的唯一情况。我认为信号量大部分时间都不是零(当然这是应用程序特定的事情)。因此,我们可以避免大量开销。

关于调度信号量的另一个评论,这是与上述情况相反的情况。如果您的线程具有不同的执行优先级,并且优先级较高的线程必须长时间锁定信号量,则调度信号量可能不是解决方案。这是因为没有"队列"在等待线程中。在这种情况下发生的是更高的优先级 线程在大多数时间获取并锁定信号量,而较低优先级的线程只能偶尔锁定信号量,因此,大多只是等待。如果此行为不适合您的应用程序,则必须考虑调度队列。