Альтернативы Mutex в быстрой
У меня есть разделяемая память между несколькими потоками. Я хочу, чтобы эти потоки не обращали внимание на эту часть памяти одновременно. (например, проблема производителя-потребителя)
Проблема
Поток добавляет элементы в очередь, а другой поток считывает эти элементы и удаляет их. Они не должны одновременно обращаться к очереди.
Одним из решений этой проблемы является использование Mutex.
Как я нашел, в Swift нет Mutex. Есть ли альтернативы в Swift?
Ответы
Ответ 1
Как люди прокомментировали (включая меня), есть несколько способов добиться такого блокирования. Но я думаю, что семафор отправки лучше других, потому что он, по-видимому, имеет наименьшие издержки. Как найдено в Apples doc, "Замена кода семафора" , он не переходит в пространство ядра, если семафор уже заблокирован (= ноль), что является единственным случаем, когда код переходит в ядро для переключения потока. Я думаю, что семафор не ноль большую часть времени (что, конечно же, относится к конкретным приложениям). Таким образом, мы можем избежать множества накладных расходов.
Еще один комментарий к отправке семафора, который является противоположным сценарием выше. Если ваши потоки имеют разные приоритеты выполнения, а потоки с более высоким приоритетом должны блокировать семафор в течение длительного времени, семафор отправки может не быть решением. Это связано с тем, что среди ожидающих потоков нет "очереди". Что происходит в этом случае, так это то, что более высокий приоритет
потоки получают и блокируют семафор большую часть времени, а потоки с более низким приоритетом могут блокировать семафор только изредка, поэтому, в основном, просто ждут. Если это поведение не подходит для вашего приложения, вы должны вместо этого рассмотреть очередь отправки.
Ответ 2
Есть много решений для этого, но я использую последовательные очереди для такого рода действий:
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")
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()
Ответ 3
Благодаря комментарию beshio вы можете использовать семафор следующим образом:
let semaphore = DispatchSemaphore(value: 1)
используйте wait перед использованием ресурса:
semaphore.wait()
// use the resource
и после использования release:
semaphore.signal()
Сделайте это в каждом потоке.