Использование актеров вместо `synchronized` - PullRequest
15 голосов
/ 21 ноября 2011

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

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

Ответы [ 2 ]

7 голосов
/ 21 ноября 2011

1) Обзор

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

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

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

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

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

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

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

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

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

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

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

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

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

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

4 голосов
/ 21 ноября 2011

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

...