18

Я время от времени занимаюсь хакерством с Ruby, но я не делал ничего большого или многопотокового с ним. Я слышал, что MRI поддерживает только зеленые потоки, а JRuby поддерживает собственные потоки через JVM. Однако я натыкаюсь на комментарии к блогам и дискуссионным группам, в которых говорится, что «Rails не является потокобезопасным» или что сам Ruby не является потокобезопасным. Например, кто-то прокомментировал, что существует проблема с требованием. Это звучит немного фундаментально.Ruby/Rails thread safety

Я видел много Java приложений, которые не обрабатывают параллелизм должным образом, и у меня есть кошмары о них время от времени :-) Но, по крайней мере, вы можете записи поточно-приложений в Java, если вам действительно знаю, что вы делаете (это просто нелегко).

Это звучит довольно тревожно, может кто-то уточнить, что именно проблема и как Rails вообще удается работать, если это так? Могу ли я написать многопоточный код Ruby, который работает корректно без условий гонки и тупиков? Является ли он переносимым между JRuby и MRI или мне нужно взломать специальный код JVM, чтобы правильно использовать собственные потоки JVM?

EDIT:

я должен был спросить два вопроса, потому что люди, кажется, только отвечать на рельсы РЕЗЬБОНАРЕЗАНИЕ вещи (что приятно само по себе) и зеленый многопоточность против родной многопоточности. Мои проблемы с основными проблемами Ruby в отношении потока безопасности на самом деле не были рассмотрены. Кажется, существует хотя бы (неразрешенный?) issue с требованием в некоторых случаях.

+0

Duplicate: http://stackoverflow.com/questions/129226/what-are-the-current-state-of-affairs-on-threading-concurrency-and-forked-proces/129331#129331 –

ответ

5

Нормальным решением для MRI является запуск нескольких экземпляров Rails, каждый запрос обработки независимо. Так как MRI не является многопоточным, вы не можете запускать несколько экземпляров Rails поверх него. Это означает, что вы берете сбой памяти, так как Rails загружается один раз за Ruby-процесс.

Поскольку JRuby поддерживает собственные потоки, вы всегда можете запускать несколько экземпляров Rails в одном JVM. Но с Rails потокобезопасными, вы можете сократить его до одного, что означает более низкое использование памяти и меньше компиляции JIT.

Charles Nutter (JRuby) имеет nice summary.

+0

Спасибо, Чарльз Сводка Nutter великолепна. – auramo

1

Я думаю, что предыдущие плакаты очень хорошо покрывали случаи Rails, поэтому я не буду заниматься такими вещами.

Конечно, можно писать приложения с ручным покрытием. Некоторые из проблем, существующих с рубиновыми потоками, состоят в том, что они «зеленые», поскольку они управляются виртуальной машиной. В настоящее время интерпретатор по умолчанию (MRI) имеет только один истинный системный поток, который должен использоваться всеми потоками, которыми управляет интерпретатор.

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

Что касается вашего вопроса, связанного с интерпретатором, я так не думаю. AFAIK вам не нужно ничего делать, чтобы заботиться о потоках JRuby/JVM.

Также: This article более на Igvita, который хорошо рассматривает состояние параллелизма в Ruby.

14

Прежде всего, Ruby 1.9 (последний официальный релиз) now uses native (kernel) threads. Предыдущие версии Ruby использовали зеленые нити. Чтобы ответить на ваш вопрос лаконично, до 1.9 потоки обычно не использовались в приложениях Ruby большими или малыми именно потому, что они не особенно безопасны или надежны.

Это не особенно тревожно, потому что до версии 2.2 Rails не пытались быть потокобезопасными, и поэтому мы обычно обрабатываем асинхронную обработку с использованием нескольких процессов, блокировки записей базы данных и очередей сообщений, таких как Starling. Это, как правило, довольно надежный способ масштабирования веб-приложения - по крайней мере, столь же надежного, как неправильно многопоточные Java-приложения, - и имеет дополнительное преимущество в том, что становится проще масштабировать ваше приложение сбоку до нескольких процессоров и серверов.

Я понятия не имею, была ли проблема с требованием, о которой вы упомянули, была решена с 1,9, но я смиренно осмелюсь предположить, что если вы динамически требуете библиотеки в новых потоках, то у вас есть несколько проблем с возможностью обслуживания.

Если вы хотите полностью исключить потоки, Ruby 1.9 also supports fibers, в которых используется совместный подход без совместного использования и, как я понимаю, проще писать и поддерживать, чем потоки. Performance numbers here.

+0

Почему полезно сравнивать * ничего * с "* неправильно * многопоточными Java-приложениями"? –

+0

@KirkWoll. Я читал, что ответчик подразумевал, что «когда потоки опасны на языке, это может быть не стоит на этом языке». – Jackson