Несинхронизированные статические методы потокобезопасны, если они не изменяют переменные статического класса?

Мне было интересно, если у вас есть статический метод, который не синхронизирован, но не изменять какие-либо статические переменные, является ли он потокобезопасным? Как насчет того, создает ли в нем локальные переменные? Например, следующий код безопасен?

public static String[] makeStringArray( String a, String b ){
    return new String[]{ a, b };
}

Итак, если у меня есть два потока, вызывающие метод ths непрерывно и одновременно, один с собаками (скажем, "дог" и "бычья собака" ), а другой с кошками (скажем, "персидский" и "сиамский" ), я когда-нибудь получу кошек и собак в том же массиве? Или кошки и собаки никогда не будут внутри одного и того же вызова метода одновременно?

Ответ 1

Этот метод является 100% потокобезопасным, даже если он не был static. Проблема с безопасностью потоков возникает, когда вам нужно обмениваться данными между потоками - вы должны заботиться об атомарности, видимости и т.д.

Этот метод работает только с параметрами , которые находятся в стеке и ссылаются на неизменяемые объекты в куче. Stack по своей сути является локальным для потока, поэтому совместное использование данных не происходит.

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

Ответ 2

Метод может быть только поточно-опасным, если он изменяет какое-то общее состояние. Является ли это статическим или нет, не имеет значения.

Ответ 3

Функция отлично защищена потоками.

Если вы думаете об этом... предположите, что произойдет, если бы это было иначе. У каждой обычной функции были проблемы с потоками, если они не синхронизированы, поэтому все функции API в JDK должны быть синхронизированы, потому что они потенциально могут быть вызваны несколькими потоками. И поскольку в большинстве случаев приложение использует какой-то API, многопоточные приложения будут практически невозможны.

Это слишком смешно, чтобы думать об этом, поэтому просто для вас: методы не являются потокобезопасными, если есть ясная причина, почему могут быть проблемы. Старайтесь всегда думать о том, что, если в моей функции было несколько потоков, и что, если бы у вас был отладчик шагов и один шаг за другим продвигался первым... тогда второй поток... может быть, второй раз... были бы проблемы? Если вы его найдете, это не будет безопасным для потока.

Также помните, что большинство классов Java 1.5 Collection не являются потокобезопасными, за исключением тех, которые указаны, например ConcurrentHashMap.

И если вы действительно хотите погрузиться в это, внимательно изучите ключевое слово volatile и ВСЕ его побочные эффекты. Посмотрите на классы Semaphore() и Lock() и их друзей в java.util.Concurrent. Прочитайте все документы API по классам. Стоит также учиться и удовлетворять.

Извините за слишком сложный ответ.

Ответ 4

Используйте ключевое слово static с синхронизированными статическими методами для изменения статических данных, общих для потоков. С ключевым словом static все созданные потоки будут бороться за одну версию метода.

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

Ответ 5

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