Если я понял, модель актера похожа на объектную модель, но с некоторыми отличиями:
- КАЖДЫЙ объект порождает свой отдельный поток, и это не проблема, даже если у вас есть тысячи объектов.
- Актеры взаимодействуют не с помощью вызова функций и получения возвращаемых значений, а с помощью отправки и получения сообщений.
- Если вы не нарушите эту модель, ваше приложение будет использовать параллелизм на полную мощность без каких-либо рисков гоночных условий.
- Все, что вы можете сделать в ОО, вы можете сделать, используя актеров, но лучше, проблема в том, что все, что мы кодировали в последние годы, было основано на ОО - но переход неизбежен.
Например, предположим, что мне нужно определить класс / вектор трехмерного вектора, создать два экземпляра и вызвать для них операцию суммирования.
ОБЪЕКТНО-ОРИЕНТИРОВАННЫЙ:
class V3d {
constructor V3d(x,y,z) //bla
float x,y,z;
function sum(V3d b)
{
return V3d(x+b.x,y+b.y,z+b.z);
}
}
//using:
mySum = V3d(1,2,3).sum(V3d(3,2,1)) //creates 2 instances, sum, returns instantly
drawPoint(mySum) //uses the result
МОДЕЛЬ АКТЕРА:
actor V3d
{
constructor V3d(x,y,z) //bla
float x,y,z;
loop
{
receive 'sum',b:V3d :
send(caller,'sumResult',V3d(x+b.x,y+b.y,z+b.z))
}
}
//using:
send(V3d(1,2,3),'sum',V3d(3,2,1)) //creates 2 instances, send to the first one a request to sum with the second one
loop
{
receive 'sumResult',result:
drawPoint(result) //receives result and draws it
}
Это оно? Или я совершенно не прав?
Ответы:
Краткий ответ - нет, это не правильно.
начинается достаточно корректно (каждый актер, по крайней мере, потенциально выполняется как независимый поток), но затем в значительной степени сбивается с пути. В модели нет ничего, что заставляло бы работать много потоков - это зависит от реализации. Самое большее, простота создания большого количества потоков оказывает давление на реализацию, чтобы обеспечить эффективную многопоточность. По крайней мере, что касается модели, любое сходство между актерами и объектами в основном случайно. «Объект» имеет довольно специфические последствия того, как вы комбинируете код и данные. Актер обычно включает в себя как код, так и данные, но мало что говорит о том, как они объединяются (кроме того факта, что единственными данными, видимыми для внешнего мира, являются сообщения).
Обычный способ описания взаимодействия - отправка сообщений, да. У меня нет удобной цитаты, но кто-то давно доказал, что такие механизмы, как виртуальные функции C ++, изоморфны отправке сообщений (так как виртуальные функции обычно реализуются, вы используете смещение в vtable - но если вы вместо этого отправил смещение в таблицу сообщений, эффект будет таким же).
Это не так просто. Если вы сможете найти копию, Генри Бейкер (вместе с кем-то, чье имя я сейчас не помню) написал статью о правилах, необходимых для согласованности данных в модели актера.
«Лучше» в лучшем случае очень субъективно. Некоторые проблемы очень параллельны по своей природе и действительно включают в себя большое количество автономных сущностей с минимальным взаимодействием, которое в основном асинхронно. В таком случае модель актера действительно может работать очень хорошо. Для других проблем это действительно не так. Некоторые проблемы почти полностью носят серийный характер. Другие могут выполняться параллельно, но при этом все же требуется тесная синхронизация между этими действиями (например, по существу режим, подобный SIMD, когда вы выполняете одну инструкцию за раз, но каждая инструкция воздействует на большое количество элементов данных). Конечно, можно решить оба этих типа проблем, используя модель актера, но для таких задач часто требуется изрядное количество дополнительной работы за небольшую или нулевую прибыль взамен.
источник
Относительно 1: я работал с однопоточным приложением, смоделированным актером, так что вполне возможно игнорировать большое количество потоков, которое это предлагает. AFAIK, потоки не являются легкими объектами в любом случае, поэтому, вероятно, не желательно иметь один для каждого актера, в зависимости от того, сколько актеров вы используете.
Относительно 3: Я почти уверен, что условия гонки могут произойти в системах, смоделированных актерами, просто из-за логики программирования?
Относительно 4: определить «лучше»? Мой опыт показывает, что асинхронную логику гораздо сложнее читать, чем синхронную логику. Например, в приведенном выше примере вы не знаете, какая операция отвечает за какой результат, поэтому необходимо выполнить дополнительное отслеживание сообщений. Как только это добавляется, а другие сообщения входят и выходят в логику, цель кода распределяется по нескольким функциям отправки / получения.
Сказав все это, я большой поклонник использования актерской модели для верхних уровней приложения. Это может облегчить разделение, поскольку добавить зависимости немного сложнее, чем добавить функцию. У меня также нет большого опыта работы с языками более высокого уровня, чем языки Java, и другие парадигмы могут поддерживать асинхронность более фундаментальным образом.
источник