(В отличие от других ответов) задокументирован контракт о безопасности потоков : посмотрите в interface
javadocs (в отличие от javadoc методов). Например, в нижней части ExecutorService javadoc вы найдете:
Эффекты согласованности памяти: действия в потоке до
отправка задачи Runnable или Callable в ExecutorService
произойдет до любые действия, выполненные этой задачей, которая, в свою очередь,
произойдет до результат получен через Future.get ().
Этого достаточно, чтобы ответить на это:
«Должен ли я синхронизировать доступ к исполнителю перед взаимодействием / отправкой задач?»
Нет, нет. Можно создавать и отправлять задания любому (правильно реализованному) ExecutorService
без внешней синхронизации. Это одна из главных целей проектирования.
ExecutorService
- это одновременная утилита , которая означает, что она разработана для обеспечения максимальной производительности без синхронизации для производительности. (Синхронизация приводит к конфликту потоков, что может снизить эффективность многопоточности, особенно при масштабировании до большого количества потоков.)
Нет никакой гарантии относительно того, в какое время в будущем задачи будут выполняться или завершаться (некоторые могут даже выполняться сразу в том же потоке, который их отправил), однако рабочий поток гарантированно увидит все эффекты, которые выполнил отправляющий поток. до момента подачи . Поэтому (поток, который запускается) ваша задача также может безопасно читать любые данные, созданные для ее использования, без синхронизации, поточно-ориентированных классов или любых других форм «безопасной публикации». Сам процесс отправки задания достаточен для «безопасной публикации» входных данных для задания. Вам просто нужно убедиться, что входные данные не будут изменены каким-либо образом во время выполнения задачи.
Точно так же, когда вы извлекаете результат задания обратно через Future.get()
, поток извлечения будет гарантированно видеть все эффекты, сделанные рабочим потоком исполнителя (в обоих возвращаемых результатах, плюс любой побочный эффект меняет работника -поточь, возможно, сделал).
Этот контракт также подразумевает, что сами задачи могут отправлять больше задач.
«Гарантирует ли ExecutorService безопасность потоков?»
Теперь эта часть вопроса гораздо более общая. Например, не удалось найти какое-либо утверждение договора о безопасности потока о методе shutdownAndAwaitTermination
- хотя я отмечаю, что пример кода в Javadoc не использует синхронизацию. (Хотя, возможно, есть скрытое предположение, что завершение работы вызвано тем же потоком, который создал Исполнитель, а не, например, рабочим потоком?)
Кстати, я бы порекомендовал книгу «Параллелизм Java на практике», чтобы стать хорошим помощником в мире параллельного программирования.