Использование актеров вместо `synchronized`

Каждый раз, когда я читал об использовании synchronized в Scala, автор обычно упоминает, что вместо этого следует использовать Актеры (this). Хотя я понимаю, как работают актеры, мне бы очень хотелось увидеть пример использования Актеров для замены модификатора метода Java synchronized (под этим я подразумеваю его Scala эквивалент - блок synchronized) в куске кода, Было бы приятно увидеть изменение внутренних элементов структуры данных.

Это хорошее использование Актеров или я был дезинформирован?

Ответы

Ответ 1

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

Ответ 2

1) Обзор

Scala Актеры могут заменить сложную бизнес-логику в стандартном Java-приложении, которое часто уклоняется от разработчиков, работающих над сложными многопоточными системами.

Рассмотрим следующий фрагмент кода java, который можно увидеть в простом, потоковом приложении (этот код ожидает завершения асинхронного запроса).

myAsyncRequest.startCalculation(); 
while(notDone)
   myAsyncRequest.checkIfDone();
   Thread.sleep(1000); 
System.out.println("Done ! Value is : " + myAsyncRequest.getCalculationValue());

Чтобы увидеть прямую замену этого типа кода с помощью модели Scala более высокого уровня concurrency, проверьте этот пост: Scala программа, выходящая перед выполнением и завершением все Scala отправленные сообщения актера. Как остановить это?

2) Теперь: вернуться к коду snpipet --- Здесь есть некоторые очевидные проблемы, давайте быстро взглянем:

  • Код связывает логику "мониторинга" выполнения расчета с обработкой вычисленных результатов.
  • В коде есть встроенные эвристики (Thread.sleep(1000)), которые не имеют четкого логического обоснования (зачем ждать секунду? Почему бы не подождать 3 секунды?), тем самым добавив ненужную логику в кодовый блок.
  • Он не масштабируется - если я запускаю 1000 клиентов, и каждый из них постоянно проверяет результаты, я могу создать довольно уродливый трафик - по какой-то веской причине.

Как Scala изменить эту парадигму?

  • Scala актеры могут возвращать "фьючерсы"

Они заключают в себе ожидание того, что, достаточно скоро, "вещь", которую вы хотите сделать актеру, будет выполнена. Scala "будущее" заменяет эту конструкцию java: она делает "явным" тот факт, что мой цикл while "ожидает" что-то произойдет в ближайшем будущем, и после этого действие должно быть выполнено.

  • Scala актеры могут передавать "сообщения"

Хотя я "жду" (в цикле while выше) для завершения, очевидно, что другой способ реализовать будет, если объект вычисления просто "скажет мне", когда это будет сделано. Передача сообщений позволяет это, но несколько сложна и приводит к непрослеживаемому, нечитаемому коду в некоторых реализациях Java. Поскольку Scala абстрагирует это понятие таким образом, чтобы оно было сконструировано с учетом одновременных рабочих нагрузок, теперь шаблон проектирования передачи сообщений может быть реализован таким образом, который не является чрезмерно сложным, тем самым отделяя логику "ожидания" от логика обработки.

3) Краткий ответ: В общем, API Scala построены для кодирования параллельной логики на более высоком уровне абстракции, поэтому вы являетесь параллельным кодом, который является декларативным, а не путается в деталях реализации.

4) Синхронизация: концепция нижнего уровня, которая, хотя и существенна, может усложнить наш код.

Синхронизация - это артефакт более низкого уровня, многопоточного программирования. Предоставляя абстракции более высокого уровня из наиболее распространенных парадигм параллельного программирования, Scala делает эту конкретную конструкцию ненужной во многих наиболее распространенных случаях одновременного программирования. Фактически, в настоящее время даже java делает это:) Пакет java.util.concurrent дает нам атомные типы данных и структуры данных, устраняя необходимость обертывания простых операций в "синхронизированных" блоках. Однако стандартная Java не поддерживает понятия более высокого уровня "Актеры" и "Фьючерсы", которые можно эффективно управлять и координировать без необходимости ручного управления синхронными вызовами методов или модификациями объектов.