функция вызова Java из нескольких потоков не объявлена ​​как поточно-безопасная - PullRequest
3 голосов
/ 08 августа 2010

Существует функция JDK, которая, хотя javadocs не объявляет ее как поточно-ориентированной, глядя на код в Google, кажется, что я могу получить желаемый результат, вызвав его из нескольких потоков без нежелательныхэффекты, так как функция использует в основном переменные стека.Так что не имеет значения, есть ли у него синхронизированные блоки.Мне интересно, если я что-то упустил и в конечном итоге столкнуться с неприятностями.Функция является connection.call (requestMsg, url);SOAPConnection от SAAJ api.Любой указатель на то, как я должен проанализировать это, чтобы решить использовать его из нескольких потоков или нет?

Спасибо!

Ответы [ 4 ]

4 голосов
/ 08 августа 2010

Ад нет .Если это не задокументировано как потокобезопасное, мы не будем это предполагать.Не берите в голову рекомендации Sun, написанные во времена Vector, Hashtable, StringBuffer, старой модели памяти Java и однопроцессорных машин.Мода перевернулась.Мы живем в совершенно другом мире java-параллелизма.

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

Для класса, который фактически предназначен для использования в нескольких потоках, он должен предоставить кропотливо подробный документ о том, как он ведет себя.Это нонсенс , чтобы пометить его как просто "потокобезопасный".Слишком много вещей, которые можно объяснить и задокументировать, проверить любой класс параллелизма.

Поэтому бессмысленно предполагать режим безопасности потока по умолчанию.Это ничего не значит.

-

Для вашего конкретного запроса, если реализация такая:

constructor()
  open socket

Response call(Request)
  write request to socket output stream
  read response from socket input stream

close()
  close socket

Без синхронизации по call (), этоочевидно небезопасно.Если у вас есть параллельное чтение / запись по TCP-соединению, хаос гарантирован.

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

1 голос
/ 08 августа 2010

Следующая цитата взята из "Как писать комментарии к документу для инструмента Javadoc"

Спецификация API платформы Java - это контракт между вызывающими и реализациями.

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

Для меня это говорит о том, что вы в идеале должны быть в состоянии предположить, что стандартные API Java являютсяпотокобезопасен, если не указано иное.Но последнее предложение говорит мне, что довольно опасно предполагать, что это всегда так.Конечно, для большинства Swing API вы НЕ ДОЛЖНЫ предполагать безопасность потоков.

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

  • Если в javadoc явно указано, что что-то является потокобезопасным, вы можете рассчитывать на то, что оно будет поточно-ориентированным в будущем.
  • Если в javadoc явно указано, что что-то не является поточно-ориентированным, вы можете полагаться на-thread-safe идти вперед.
  • Если javadoc ничего не говорит, а тщательный анализ исходного кода говорит вам, что он поточно-ориентированный, вы можете положиться на то, что он ориентирован на многопоточность в будущем.
  • Если javadoc ничего не говорит, а тщательный анализ исходного кода говорит вам, что он не является поточно-ориентированным, все ставки отключены.Это может быть ошибка Javadoc или недостаток текущей реализации.

(Это основано на наблюдении, что Sun / Oracle вряд ли внесут изменения, нарушающие обратную совместимость. Изменение характеристик безопасности потокастандартных API может привести к коварным ошибкам параллелизма ... и поэтому вдвойне маловероятно.)

1 голос
/ 08 августа 2010

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

Главное - проверить, существуют ли какие-либо общие переменные между потоками и будет ли на них воздействовать одновременный вызов двумя или более потоками. Конечно, это может быть длительным и сложным процессом, поскольку класс может состоять из нескольких других классов, которые, в свою очередь, состоят из нескольких других.

Если бы это был я, я бы реструктурировал свой код, чтобы избежать многопоточного вызова, так как отладка была бы кошмаром, и я не могу гарантировать, что он будет работать 100% времени. *

Это ваш зов: как сказал Грязный Гарри: «Тебе сегодня повезло? Хорошо?»

На другой ноте я ответил на этот вопрос , и ответ также может относиться к этому.

0 голосов
/ 08 августа 2010

Общее правило заключается в том, что методы и классы являются потокобезопасными, если не указано иное.Так, например, методы RMI поточнобезопасны, то же самое.

...