Может ли поток наблюдать нежелательные значения в объекте из-за непоследовательности памяти?

После долгих исследований я считаю, что хорошо понимаю JMM, конечно же, достаточно хорошо, чтобы понимать, что когда объект разделяется между двумя потоками, вы должны синхронизировать весь доступ на одном мониторе. Я понимаю, что если несколько активных потоков обращаются к объекту одновременно, все ставки отключаются относительно того, что они будут наблюдать.

Однако, если объект детерминирован и фактически создан до запуска какого-либо другого потока, который его использует (или этот поток даже создан), гарантирует ли JMM, что содержимое объекта, видимого более поздним потоком, будет таким же, как было настроено ранее настроенный поток.

Можно ли впервые обратиться к объекту в потоке и наблюдать за загрязненной памятью, например, из-за кеширования процессора, а не из-за реального содержимого объекта? Или JMM гарантирует, что при первом получении ссылки на любой данный объект память, на которую он ссылается, является связной?

Я спрашиваю, потому что есть один конкретный шаблон, который я использую в ряде мест, в котором я до сих пор не уверен. Часто у меня есть объект, который сконструирован и настроен по частям, а затем неизменно используется. Поскольку он настроен на частичную еду, ни один из его членов не может быть окончательным (и я не хочу менять их все на шаблон строителя, если не буду вынужден).

Например, создание обработчика HTTP-соединения и добавление подключаемых объектов для обработки определенных HTTP-запросов. Обработчик создается и настраивается с использованием мутаторов, а затем устанавливается в процессор соединений TCP, который использует пул потоков для обработки соединений. Поскольку обработчик соединений настраивается и устанавливается до запуска пула потоков процессора соединений и никогда не изменяется после установки в процессор соединений, я не использую явную синхронизацию между потоком, который все настраивает, и потоками, которые обрабатывают соединения.

В этом конкретном случае вероятно, что конфигурация потока также является тем же потоком, который запускает пул потоков, и, поскольку запуск пула потоков синхронизирован, все потоки, которые из него заканчиваются, также синхронизируются с тем же объектом пула потоков, поэтому может маскировать любую основную проблему (мой API не требует, чтобы начальный поток был таким же, как поток конфигурирования).

2 ответа

Решение

Обычно при взаимодействии потоков у вас должны быть отношения " до того". Например, как предусмотрено параллельными очередями. Нет необходимости в более точной синхронизации.

Редкий случай передачи объектов между потоками без связей " происходит до" известен как небезопасная публикация. Есть правила, связанные с использованием final поля, которые позволяют сделать это безопасным. Тем не менее, вы должны очень редко надеяться на это.

Всегда существует связь между вызовом start на поток, и выполнение потока. Таким образом, если объект безопасно опубликован в начальном потоке перед запуском, запущенный поток также будет видеть объект связно.

Разве пометка переменной "volatile" не мешает потокам видеть "грязные" значения?

Другие вопросы по тегам