互联网中的互斥替代品

ric*_*ick 16 concurrency mutual-exclusion ios swift swift3

我有多个线程之间的共享内存.我想阻止这些线程同时访问这段内存.(像生产者 - 消费者问题)

问题:

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

该问题的一个解决方案是使用Mutex.

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

Dev*_*ini 10

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

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

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

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")
        semaphore.wait()  // requesting the resource

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

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

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

RunLoop.main.run()
Run Code Online (Sandbox Code Playgroud)


bes*_*hio 8

正如人们评论的那样(包括我),有几种方法可以实现这种锁定。但我认为 dispatch semaphore 比其他的更好,因为它似乎开销最少。正如在 Apples文档“替换信号量代码”中发现的那样除非信号量已经锁定(= 零),否则它不会进入内核空间,这是代码进入内核以切换线程的唯一情况。我认为信号量大部分时间都不是零(不过,这当然是特定于应用程序的问题)。因此,我们可以避免大量开销。

另一个关于 dispatch semaphore 的评论,与上面的场景相反。如果你的线程有不同的执行优先级,并且更高优先级的线程不得不长时间锁定信号量,调度信号量可能不是解决方案。这是因为等待线程之间没有“队列”。在这种情况下发生的情况是,高优先级线程在大部分时间获取并锁定信号量,而低优先级线程只能偶尔锁定信号量,因此,大多数情况下只是等待。如果此行为对您的应用程序不利,则必须考虑使用调度队列。


A.b*_*bee 6

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

let semaphore = DispatchSemaphore(value: 1)
Run Code Online (Sandbox Code Playgroud)

在使用资源之前使用等待:

semaphore.wait()
// use the resource
Run Code Online (Sandbox Code Playgroud)

并在使用release之后:

semaphore.signal()
Run Code Online (Sandbox Code Playgroud)

在每个线程中执行此操作。