Вопрос по java – Синхронизация, когда использовать или не использовать?
=======================================================================

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

```
public static synchronized List<AClass> sortA(AClass[] aArray) 
{
    List<AClass> aObj = getList(aArray);

    Collections.sort(aObj, new AComparator());

    return aObj;
}

public static synchronized List<AClass> getList(AClass[] anArray) 
{
    //It converts an array to a list and returns
}

```

**a different array** тогда никакая синхронизация не требуется, потому что остальные переменные являются локальными.

Если вместо этого вы запустите несколько потоков, все вызовы`sortA` и передать ссылку на тот же массив,**you'd be in trouble** без`synchronized`потому что они будут мешать друг другу.

Остерегайтесь, что из примера может показаться, что`getList` метод возвращает новый`List` из массива, так что даже если потоки проходят один и тот же массив, вы получаете разные`List` объекты. Это вводит в заблуждение. Например, используя`Arrays.asList` создает`List` поддержанный данным массивом, но Javadoc ясно заявляет, что`Changes to the returned list "write through" to the array.` так что будь осторожен с этим.



 как вы правильно поняли, влияет на пропускную способность вашего приложения, а также может привести к истощению потоков.

Все get в основном должны быть не блокирующими, как реализовано в Collections in concurrency package.

Как в вашем примере все вызывающие потоки передадут туда свою копию массива,`getList` не нужно синхронизировать, поэтому`sortA` Метод, как и все остальные переменные являются локальными.

Локальные переменные живут в стеке, и каждый поток имеет свой собственный стек, поэтому другие потоки не могут ему помешать.

Вам требуется синхронизация, когда вы изменяете состояние объекта, которое другие потоки должны видеть в согласованном состоянии, если ваши вызовы не изменяют состояние объекта, который вам не требуется для синхронизации.



 поэтому их не нужно синхронизировать.



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



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

В приведенном выше фрагменте кода нет данных для обмена. Методы работают с предоставленным вводом и возвращают вывод. Если несколько потоков вызывают один из ваших методов, каждый вызов будет иметь свой собственный ввод и вывод. Следовательно, нет никаких шансов непоследовательности нигде. Таким образом, ваши методы в приведенном выше фрагменте не должны быть синхронизированы.

Синхронизация, если она используется излишне, наверняка приведет к снижению производительности из-за задействованных накладных расходов и, следовательно, должна использоваться с осторожностью только при необходимости.