Ответ 1
Можно рассмотреть две вещи: передать сообщение и правильно опубликовать внутреннее состояние актеров.
Первая достигается реализацией MessageQueue почтовых ящиков, которая будет использовать волатильные записи (для ConcurrentLinkedQueue по умолчанию) или блокировки (для обычного LinkedBlockingQueue), чтобы обеспечить безопасную публикацию объекта, помещенного в очередь. Актер будет синхронизироваться с отправителем, читая те же самые изменчивые поля (в первом случае) или беря одни и те же блокировки (во втором), поэтому все записи до отправки сообщения случаются - перед чем-либо внутри актера при обработке этого сообщения.
Внутреннее состояние актеров безопасно убирается, даже когда оно переносится по другому потоку по статусу почтового ящика, который вы нашли: после обработки пакета сообщений (определенного параметром throughput
) почтовый ящик установлен на "нет" запланированный "статус, который является volatile write (фактически Unsafe.compareAndSetInt()
, который имеет ту же семантику). Перед тем, как актер начинает обрабатывать сообщения, он считывает статус почтового ящика с помощью Unsafe.getIntVolatile
, который синхронизируется с предыдущей записью, поэтому все записи, сделанные актером во время последней серии сообщений, происходят до того, как все прочитает во время этой партии.
Подробнее о семантике задействованных операций можно прочитать здесь, имея в виду, что методы *Volatile
на sun.misc.Unsafe
подчиняются тем же правилам, что и для Atomic*Reference
.