Java многопоточность и безопасная публикация - PullRequest
35 голосов
/ 29 апреля 2009

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

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

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

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

Ответы [ 6 ]

20 голосов
/ 29 апреля 2009

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

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

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

5 голосов
/ 29 апреля 2009

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

Да, абсолютно. Даже самое тривиальное веб-приложение должно сталкиваться с проблемами, связанными с параллелизмом. К сервлетам обращаются, например, из нескольких потоков.

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

2 голосов
/ 29 апреля 2009

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

2 голосов
/ 29 апреля 2009

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

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

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

1 голос
/ 29 апреля 2009

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

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

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

1 голос
/ 29 апреля 2009

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

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

...