Ruby - Неизменяемые объекты
-
03-07-2019 - |
Вопрос
У меня есть многопоточное приложение, написанное на Ruby, которое совместно использует несколько переменных экземпляра.Операции записи в эти переменные редки (1%), в то время как операции чтения очень распространены (99%). Каков наилучший способ (либо по вашему мнению, либо в идиоматическом стиле Ruby) гарантировать, что эти потоки всегда видят самые актуальные значения? Вот несколько идей, которые у меня уже были (хотя я хотел бы услышать ваше мнение, прежде чем я пересмотрю это).:
- Имейте блокировку, которая чаще всего используется перед чтением или записью любой из этих переменных (из Параллелизм Java на практике).Недостатком этого является то, что это накладывает много
synchronize
блоки в моем коде, и я не вижу простого способа избежать этого. - Используйте Ruby's
freeze
способ (см. здесь), хотя это выглядит одинаково громоздко и не дает мне никаких преимуществ синхронизации, которые дает первый вариант.
Оба этих варианта кажутся довольно похожими, но, надеюсь, у кого-нибудь найдется идея получше (или он сможет хорошо аргументировать одну из этих идей).Я также был бы не против сделать объекты неизменяемыми, чтобы они не были повреждены или изменены в середине операции, но я недостаточно хорошо знаю Ruby, чтобы выполнить вызов самостоятельно и этот вопрос кажется, утверждается, что объекты сильно изменчивы.
Решение
Использование блокировки - наиболее подходящий способ сделать это.Вы можете ознакомиться с презентацией Джима Вейриха на эту тему: Что Должен знать Каждый Рубинист О Нарезании резьбы.
Кроме того, замораживание объекта здесь вам не поможет, поскольку вы хотите изменить эти переменные.Замораживание их на месте означает, что никакие дальнейшие изменения к ним применяться не будут (и, следовательно, ваш 1% записей не будет работать).
Другие советы
Я сам им не пользовался, но вы, возможно, захотите проверить Поток данных.Это заставляет все переменные записываться один раз.
Блокировка чтения-записи - это распространенная проблема с четко определенным решением:
и существует множество его реализаций:
Вы не хотите устанавливать блокировку для каждого чтения / записи
Вы должны использовать мьютекс для синхронизации доступа к общему состоянию.На самом деле нет никакого способа избежать этого.
На современных многоядерных компьютерах вы не можете делать никаких предположений о том, как будет осуществляться доступ к памяти или как доступ к памяти будет взаимодействовать с кэшированием.