Безопасна ли двойная проверка блокировки в Ruby? - PullRequest
2 голосов
/ 10 апреля 2009

В этой статье говорится, что двойная проверка блокировки небезопасна для определенных комбинаций языка и оборудования, когда совместно используемую переменную можно обновить со ссылкой на объект, который инициализирован только частично.

Мне было интересно: это относится и к Ruby? Это зависит от реализации Ruby на платформе, на которой он запущен, или правильное поведение подробно описано в спецификации языка?

Ответы [ 3 ]

4 голосов
/ 07 сентября 2009

Двойная проверка в Java опасна, потому что значение может быть присвоено переменной до того, как конструктор будет фактически завершен. В Ruby этого не происходит: создание объекта - это то же самое, что присвоение результата вызова функции переменной, потому что конструкторы - это просто нормальные функции. Назначение произойдет только после полного завершения конструктора.

На МРТ назначение является атомным. Официального описания языка Ruby или модели памяти не существует, но альтернативные реализации, как правило, изо всех сил стараются имитировать поведение МРТ даже до самых неясных деталей. Атомарность оператора присваивания является довольно важным поведением, поэтому я ожидаю, что присваивания в альтернативных реализациях Ruby также атомарны.

Если вы не возражаете против случайного создания двух объектов во время состязания, когда один объект будет собирать мусор позже, поскольку он дублируется, тогда вы можете использовать оператор || =, например:

@singleton ||= FooBar.new

|| = атомарно присваивает результат заданного выражения переменной, но только если переменная еще не была установлена. Вы можете получить два экземпляра FooBar.new, но будет доступен только один. Ruby on Rails использует эту технику внутренне, чтобы избежать использования мьютексов в некоторых местах.

4 голосов
/ 13 апреля 2009

Какая реализация Ruby? Ruby 1.8, 1.9 и JRuby имеют совершенно разные реализации потоков, так что это может быть невозможно сказать.

У меня нет ответа на ваш вопрос, но, похоже, вы пытаетесь написать быстрый параллельный код на Ruby. Мой опыт работы с Ruby 1.8 заключается в том, что это не разумная цель. Ruby 1.9 может быть лучше, но все еще имеет глобальную блокировку интерпретатора, такую ​​как Python.

Если вы пишете код на Ruby, где вы рассматриваете такие потенциально опасные оптимизации для снижения производительности, вам, вероятно, следует подумать об использовании другого языка. Идиоматический рубин имеет тенденцию подчеркивать удобочитаемость и выразительность перед эффективностью и скоростью. Попытка выжать увеличение скорости и повышение надежности из МРТ было для меня разочарованием.

Я некоторое время работал над проектом Ruby, который только что вступил в фазу, когда мы серьезно смотрим на оптимизацию. Запуск проекта в JRuby и замена узких мест, реализованных в Ruby библиотеками Java, привели к довольно заметному увеличению скорости и надежности при относительно небольших усилиях с нашей стороны.

JRuby не совершенен, но его интеграция с Java оказалась полезной и простой. Если вы не можете использовать JRuby для своего проекта, или вам удобен C, но не Java, и вы уверены, что можете написать безопасный C без утечек памяти, лучше всего написать расширения C для Ruby 1.8 или 1.9.

Прошу прощения, если этот вопрос носил чисто академический характер. Возможно, если бы вы могли сообщить нам, что именно вы пытаетесь сделать?

0 голосов
/ 09 ноября 2013

Диркьян Буссинк (@dbussink) выступил на RubyConf с докладом на эту тему. Вы захотите проверить его выступление, как только оно станет доступным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...