IMO, правильный инструмент здесь - os_unfair_lock
.Смысл двойной проверки блокировки состоит в том, чтобы избежать затрат на полную блокировку ядра.os_unfair_lock
обеспечивает это в неоспоримом случае.«Недобросовестная» часть этого в том, что он не дает обещаний ожидающим потокам.Если один поток разблокируется, то разрешается повторная блокировка без возможности получения другим ожидающим потоком (и, следовательно, может голодать).На практике с очень маленьким критическим разделом это не актуально (в этом случае вы просто проверяете локальную переменную на ноль).Это примитив более низкого уровня, чем отправка в очередь, что очень быстро, но не так быстро, как unsair_lock, так как он опирается на примитивы, такие как unfair_lock.
final class Builder<I> {
private let body: () -> I
private var lock = os_unfair_lock()
init(body: @escaping () -> I) {
self.body = body
}
private var _value: I!
var value: I {
os_unfair_lock_lock(&lock)
if _value == nil {
_value = body()
}
os_unfair_lock_unlock(&lock)
return _value
}
}
Обратите внимание, что вы были правы сделатьсинхронизация по syncIsSet
.Если бы вы рассматривали его как примитив (как это обычно бывает при других двойных проверках синхронизации), то вы полагались бы на вещи, которые Swift не обещает (как на атомизацию написания Bools, так и на то, что он фактически проверяет логическое значение).дважды, так как нет volatile
).Учитывая, что вы делаете синхронизацию, сравнение между os_unfair_lock и отправкой в очередь.
При этом, по моему опыту, такая лень почти всегда неоправданна в мобильных приложениях.Это на самом деле экономит ваше время, только если переменная очень дорогая, но, вероятно, никогда не доступна.Иногда в массово параллельных системах возможность перенести инициализацию имеет смысл, но мобильные приложения работают на довольно ограниченном количестве ядер, поэтому, как правило, не хватает лишних ядер, чтобы скрыть это.Как правило, я бы не стал заниматься этим, если вы уже не обнаружили, что это серьезная проблема, когда ваша платформа используется в живых системах.Если да, то я рекомендую профилировать ваш подход по отношению к os_unfair_lock
в реальных ситуациях, которые показывают эту проблему.Я ожидаю, что os_unfair_lock
победит.