Мне было интересно, если у вас есть статический метод, который не синхронизируется, но не изменяет статические переменные, это потокобезопасно? А что, если метод создает локальные переменные внутри него? Например, является ли следующий код потокобезопасным?
public static String[] makeStringArray( String a, String b ){
return new String[]{ a, b };
}
Поэтому, если у меня есть два потока, вызывающих этот метод непрерывно и одновременно, один с собаками (скажем, «великий датчанин» и «собака-бык»), а другой с кошками (скажем, «персидский» и «сиамский»), я когда-нибудь получу кошек и собак в том же массиве? Или кошки и собаки никогда не будут находиться внутри одного и того же вызова метода в одно и то же время?
Ответы:
Этот метод на 100% безопасен для потоков, так было бы, даже если бы не было
static
. Проблема с безопасностью потоков возникает, когда вам нужно обмениваться данными между потоками - вы должны заботиться об атомарности, видимости и т. Д.Этот метод работает только с параметрами, которые находятся в стеке, а ссылки на неизменяемые объекты - в куче. Стек по своей природе является локальным для потока , поэтому обмен данными никогда не происходит.
Неизменяемые объекты (
String
в данном случае) также являются поточно-ориентированными, поскольку после их создания они не могут быть изменены, и все потоки видят одно и то же значение. С другой стороны, если бы метод принимал (изменяемый), уDate
вас могли бы быть проблемы. Два потока могут одновременно изменять один и тот же экземпляр объекта, вызывая состояние гонки и проблемы с видимостью.источник
Метод может быть потокобезопасным только в том случае, если он изменяет некоторое общее состояние. Является ли это статическим или нет, не имеет значения.
источник
Эта функция совершенно безопасна для потоков.
Если вы думаете об этом ... предположите, что случилось бы, если бы это было иначе. У каждой обычной функции были бы проблемы с потоками, если бы они не были синхронизированы, поэтому все функции API в JDK должны были бы быть синхронизированы, потому что они могли бы потенциально вызываться несколькими потоками. И поскольку в большинстве случаев приложение использует какой-то API, многопоточные приложения были бы фактически невозможны.
Это слишком нелепо, чтобы думать об этом, так что только для вас: методы не являются потокобезопасными, если есть явная причина, по которой могут возникнуть проблемы. Старайтесь всегда думать о том, что если бы в моей функции было несколько потоков, а что, если бы у вас был пошаговый отладчик, и один шаг за другим продвигал бы первый ... затем второй поток ... может быть, второй снова ... будут ли проблемы? Если вы найдете один, это не потокобезопасный.
Также имейте в виду, что большинство классов Java 1.5 Collection не являются потокобезопасными, за исключением тех, где указано, например, ConcurrentHashMap.
И если вы действительно хотите погрузиться в это, внимательно посмотрите на ключевое слово volatile и ВСЕ его побочные эффекты. Посмотрите на классы Semaphore () и Lock () и их друзей в java.util.Concurrent. Прочитайте все документы API вокруг классов. Стоит учиться и сытно тоже.
Извините за этот слишком сложный ответ.
источник
Используйте
static
ключевое слово с синхронизированными статическими методами, чтобы изменить статические данные, общие для потоков. Сstatic
ключевым словом все созданные потоки будут бороться за одну версию метода.Использование
volatile
ключевого слова вместе с синхронизированными методами экземпляров гарантирует, что каждый поток имеет свою собственную копию общих данных и никакие операции чтения / записи не будут просачиваться между потоками.источник
Строковые объекты, являющиеся неизменяемыми, являются еще одной причиной вышеописанного поточно-безопасного сценария. Вместо этого, если используются изменяемые объекты (скажем, makeMutableArray ..), то безопасность потоков наверняка нарушится.
источник