Scala актеры против потоков и блокировка ввода-вывода - PullRequest
18 голосов
/ 24 января 2012

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

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

Учитывая это, как действуют актеры, когда вам нужно выполнять такие операции ввода-вывода? Существуют ли операции, которые «блокируют актера», приостанавливая действия актера, позволяя потоку переходить к другим операциям (подобно тому, как операции блокировки приостанавливают поток, одновременно позволяя процессору переходить к другим операциям), или это все, что написано в CPS, с цепочкой актеры? Или актеры просто не подходят для такой длительной операции?

Справочная информация: у меня есть опыт написания многопоточных материалов классическим способом, и я прекрасно понимаю, как работают циклы CPS / событий, но у меня нет абсолютно никакого опыта работы с актерами, и я просто хочу понять на высоком уровне, как они вписываются, прежде чем я углублюсь в код.

Ответы [ 2 ]

2 голосов
/ 27 января 2012

Это не проблема правильности, потому что библиотека актера будет порождать больше потоков по мере необходимости (верно?)

Насколько я понимаю, это не правильно. Актер блокируется, и отправка ему другого сообщения заставляет это сообщение оставаться в почтовом ящике актера, пока этот актер не сможет receive его или react к сообщению.

В Программировании в Scala (1) прямо указывается, что актеры не должны блокироваться. Если действующему субъекту необходимо выполнить что-то длительное, он должен передать работу второму действующему субъекту, чтобы основной действующий субъект мог освободиться и перейти к чтению дополнительных сообщений из своего почтового ящика. После того, как работник завершил работу, он может сообщить об этом факте главному действующему лицу, которое может закончить делать то, что должен.

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

(1) Глава 32.5 Программирование в Scala (Одерское, Второе издание, 2010)

РЕДАКТИРОВАТЬ: Я нашел это:

Метод планировщика свойства Actor можно переопределить, чтобы он возвращал ResizableThreadPoolScheduler, который изменяет размер своего пула потоков, чтобы избежать голодания, вызванного акторами, которые вызывают произвольные методы блокировки.

Нашел по адресу: http://www.scala -lang.org / api / current / scala / актеры / Actor.html

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

1 голос
/ 27 января 2012

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

Так что, если вы хотите сделать несколькоДля операции блокировки, такой как чтение из файла, вы должны создать актер FileReader, который использует неблокирующий API для чтения и записи из файла.И пусть ваш другой актер использует этого актера (отправляет и получает сообщение) в качестве API для чтения и записи в файл.

...