0Pricing
Ruby Academy · Урок

Ractors

Настоящий параллелизм

«Ractors» — бесплатный урок Ruby Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Ruby Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Ruby Academy содержит 4 уроков всего.

Что такое актор Ractor

Актор Ractor (актор Ruby) — это примитив конкурентного выполнения, появившийся в Ruby 3 и обеспечивающий настоящий параллелизм. Каждый актор Ractor самостоятельно выполняет код Ruby, поэтому два актора Ractor могут одновременно использовать два ядра CPU.

  • Акторы Ractor не используют общие изменяемые объекты, что позволяет обойти ограничение GVL.
  • Они обмениваются сообщениями.

Акторы Ractor всё ещё экспериментальны, поэтому Ruby выводит предупреждение при их использовании.

Создание актора Ractor

Создайте его с помощью Ractor.new и блока. Блок выполняется параллельно. Используйте take, чтобы получить итоговое значение блока.

r = Ractor.new do
  2 + 3
end

puts r.take

Нет общего состояния

Главное правило: акторы Ractor не могут свободно использовать общие изменяемые объекты. Блок актора Ractor не захватывает внешние локальные переменные так, как это делает обычный блок. Данные необходимо передавать явно.

Именно такая изоляция делает параллельное выполнение безопасным без блокировок.

Передача аргументов внутрь

Аргументы Ractor.new передаются параметрам блока. Это безопасный способ передать данные в актор Ractor.

r = Ractor.new(10) do |x|
  x * x
end

puts r.take

Отправка сообщений

У акторов Ractor есть входящие сообщения. Отправляйте сообщения с помощью ractor.send(value), а внутри блока принимайте их с помощью Ractor.receive.

r = Ractor.new do
  msg = Ractor.receive
  "got: " + msg
end

r.send("hello")
puts r.take

Отправка и получение

Два направления обмена данными:

  • Отправка: передайте данные в актор Ractor с помощью send, а прочитайте их с помощью Ractor.receive.
  • Получение: актор Ractor выдаёт данные с помощью Ractor.yield, а внешний код читает их с помощью take.

Вместе эти возможности позволяют создавать из акторов конвейеры.

r = Ractor.new do
  Ractor.yield 1
  Ractor.yield 2
end

puts r.take
puts r.take

Замороженные объекты и объекты, доступные для совместного использования

Некоторые объекты можно использовать совместно в разных акторах Ractor, поскольку их нельзя изменить: true, false, nil, числа, символы и объекты, замороженные вместе со всем содержимым.

Ractor.make_shareable замораживает граф объектов, чтобы им можно было безопасно пользоваться совместно.

data = Ractor.make_shareable([1, 2, 3])
puts "Frozen? " + data.frozen?.to_s

Копирование и перемещение

Когда Вы отправляете объект, которым нельзя безопасно делиться, Рактор по умолчанию выполняет его глубокое копирование, чтобы у каждой стороны была собственная копия. Вместо этого его можно переместить с помощью send(obj, move: true): владение передаётся, а исходный объект становится непригодным для использования.

Перемещение позволяет избежать затрат на копирование больших объектов.

Параллельная работа

Распределяйте ресурсоёмкую для CPU работу между раторами и собирайте результаты. Поскольку каждый из них выполняется независимо, это позволяет задействовать несколько ядер.

ractors = (1..3).map do |n|
  Ractor.new(n) do |x|
    x * 100
  end
end

results = ractors.map(&:take)
puts "Results: " + results.join(", ")

Ракторы и потоки

Сравнение:

  • Потоки используют общую память и требуют блокировок; ракторы изолированы и взаимодействуют с помощью сообщений.
  • Потоки не выполняют параллельно вычислительную работу Ruby; ракторы выполняют.
  • Ракторы строже, что предотвращает множество ошибок параллелизма.

Компромисс заключается в более жёстких правилах совместного использования данных.

Когда использовать ракторы

Выбирайте ракторы, когда:

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

Помните, что ракторы являются экспериментальной функцией: API могут измениться, а многие гемы пока не готовы к работе с раторами.

Быстрая проверка

Проверьте своё понимание раторов.

Итоги: ракторы

Вы изучили параллельное выполнение внутри процесса с помощью раторов:

  • Ractor.new выполняет код параллельно; take получает его результат.
  • Передавайте данные через аргументы или send; получайте их с помощью Ractor.receive.
  • Объекты копируются или перемещаются, а не используются совместно без ограничений.
  • Ractor.make_shareable замораживает данные для безопасного совместного использования.

На этом завершается курс по конкурентности Ruby: потоки, GVL, волокна и ракторы.

Часто задаваемые вопросы

Урок «Ractors» бесплатный?

Да — полный текст урока «Ractors» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Ruby Academy, подпишись на CoddyKit PRO. Курс Ruby Academy содержит 4 уроков всего.

Чему я научусь в уроке «Ractors»?

Настоящий параллелизм Ты практикуешь Ruby Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Ruby Academy?

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

Сколько времени занимает урок «Ractors»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Ruby Academy?

Да. Каждый урок Ruby Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Потоки
  2. Объяснение GVL
  3. Волокна
  4. Ractors
← Назад к Ruby Academy