Java многопоточность и безопасная публикация

После прочтения " Java на практике" и " OSGI на практике" Я нашел конкретную тему очень интересной; Безопасная публикация. Ниже приведено описание JCIP:

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

  • Инициализация ссылки на объект из статического инициализатора.
  • Сохранение ссылки на него в поле volatile.
  • Сохранение ссылки на это в конечном поле.
  • Сохранение ссылки на него в поле, которое должным образом защищено (синхронизированной) блокировкой.

Мой первый вопрос: сколько java-разработчиков знают об этом (проблема)? Сколько реальных Java-приложений действительно следуют за этим, и действительно ли это настоящая проблема? У меня такое чувство, что 99% реализованных JVM там не являются "злом", т.е. Нить не гарантируется (на самом деле ее практически (практически) "невозможно" ) видеть устаревшие данные только потому, что эта ссылка не соответствует "безопасная идиома публикации" выше.

Ответ 1

Пропорционально, наверное, справедливо сказать, что очень немногие программисты достаточно понимают синхронизацию и concurrency. Кто знает, сколько там серверных приложений сейчас управляет финансовыми транзакциями, медицинскими записями, полицейскими записями, телефонией и т.д. И т.д., Которые полны ошибок синхронизации и по существу работают случайно или очень часто изредка терпят неудачу (никогда не слышали о том, w600 > телефонный звонок, добавленный к их телефонному счету?) по причинам, которые никогда не смотрелись или не дошли до конца.

Публикация объектов - это особая проблема, потому что ее часто упускают из виду, и это место, где вполне разумно для компиляторов делать оптимизацию, которая может привести к неожиданному поведению, если вы не знаете об этом: в JIT-компилированном коде, хранящем указатель, а затем увеличивать его и хранить данные - это очень разумная вещь. Вы можете подумать, что это "зло", но на низком уровне это действительно так, как вы ожидали бы спецификации JVM. (Кстати, я слышал о реальных программах, запущенных в JRockit, страдающих от этой проблемы - это не чисто теоретическое.)

Если вы знаете, что ваше приложение имеет ошибки синхронизации, но не ошибается в вашей текущей JVM на вашем текущем оборудовании, тогда (a) поздравления; и (б), сейчас пришло время начать "спокойно идти к выходу из огня", фиксировать свой код и обучать своих программистов, прежде чем вам понадобится обновить слишком много компонентов.

Ответ 2

"это действительно настоящая проблема?"

Да, абсолютно. Даже самое тривиальное веб-приложение должно решать проблемы, связанные с concurrency. Например, для сервлета доступны несколько потоков.

Другая проблема заключается в том, что threading и concurrency очень сложно обрабатывать правильно. Это почти слишком сложно. Вот почему мы видим тенденции, такие как транзакционная память, и такие языки, как Clojure, которые, как мы надеемся, облегчают работу с w391. Но у нас есть путь, прежде чем они станут основным потоком. Таким образом, мы должны делать все, что у нас есть. Чтение JCiP - очень хорошее начало.

Ответ 3

Во-первых, "безопасная публикация" на самом деле не является идиомой (ИМО). Это происходит прямо из языка.

Были случаи проблем с небезопасной публикацией с использованием, например, NIO.

Большинство Java-кода очень плохо написаны. Резьбовый код, очевидно, более сложный, чем средний код бизнес-класса.

Ответ 4

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

Ответ 5

Я бы сказал, что очень немногие программисты ушли от этой проблемы. Когда вы видели последний пример кода, который использовал ключевое слово volatile? Однако большинство других условных упоминаний - я просто принял как должное как лучшие практики.

Если разработчик полностью игнорирует эти условия, они быстро столкнутся с многопоточными ошибками.

Ответ 6

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

В частности, с веб-приложениями вы часто можете уйти от этого или, по крайней мере, сойти с рук. Если у вас есть spring -установленные экземпляры, управляющие созданием объектов и сервлетами без состояния, вы часто можете притворяться, что синхронизации нет, и это сортировка, в которой заканчивается множество приложений. В конце концов кто-то начинает сдавать какое-то общее состояние, где он не принадлежит, а через 3 месяца кто-то замечает некоторые странные прерывистые ошибки. Это часто "достаточно хорошо" для многих людей (если вы не пишете банковские транзакции).

Сколько java-разработчиков знают об этой проблеме? Трудно сказать, так как это сильно зависит от того, где вы работаете.