Вопрос по synchronized
От: pva  
Дата: 25.10.23 16:42
Оценка:
Привет,

ревьюил тут код свой и возник вопрос по синхронизации:
    final private LinkedList<Integer> numbers = new LinkedList<>();
...
        synchronized (this.numbers) { // sync on the same instance, w/o special lock
            this.numbers.addAll(other.numbers);
        }
Есть ли разница синхронизироваться на внешнем объекте (как во многих руководствах) или код выше вполне себе допустим?
Есть ли ограничения приведенного выше кода?

Попутно есть еще такой вопрос:
Правильно ли я понимаю что для синхронизированных коллекций, например
    final private LinkedList<Integer> numbers = Collections.synchronizedList(new LinkedList<>());
При использовании коллекции в цикле
    for (Integer number: numbers) ...
коллекция будет лочится на все время цикла для обеспечения целостности итераторов?
Или корректно было бы сделать
    final private LinkedList<Integer> local;
    synchronized(this.lock) { local = new LinkedList<>(this.numbers); }
    for (Integer number: local) ...
?
newbie
Re: Вопрос по synchronized
От: GarryIV  
Дата: 25.10.23 16:58
Оценка: +2
Здравствуйте, pva, Вы писали:

pva>ревьюил тут код свой и возник вопрос по синхронизации:

pva>
    final private LinkedList<Integer> numbers = new LinkedList<>();
pva>...
pva>        synchronized (this.numbers) { // sync on the same instance, w/o special lock
pva>            this.numbers.addAll(other.numbers);
pva>        }
pva>
Есть ли разница синхронизироваться на внешнем объекте (как во многих руководствах) или код выше вполне себе допустим?

pva>Есть ли ограничения приведенного выше кода?
numbers не публичный так что если ты не отдаешь его наружу (а ты не должен) то нет проблем (в том числе и со стороны "руководств").

pva>Попутно есть еще такой вопрос:

pva>Правильно ли я понимаю что для синхронизированных коллекций, например
pva>
    final private LinkedList<Integer> numbers = Collections.synchronizedList(new LinkedList<>());
При использовании коллекции в цикле

pva>
    for (Integer number: numbers) ...
коллекция будет лочится на все время цикла для обеспечения целостности итераторов?

нет не будет

pva>Или корректно было бы сделать

pva>
pva>    final private LinkedList<Integer> local;
pva>    synchronized(this.lock) { local = new LinkedList<>(this.numbers); }
pva>    for (Integer number: local) ...
pva>
?

оно конечно решит проблему ( как и synchronized (this.numbers) )
но в жабе есть конкурентные коллекции же примерно 100 лет как в частности CopyOnWriteArrayList примерно вот это и делает.
про Collections.synchronizedList забудь вообще.
WBR, Igor Evgrafov
Отредактировано 25.10.2023 17:03 GarryIV . Предыдущая версия .
Re[2]: Вопрос по synchronized
От: pva  
Дата: 25.10.23 17:10
Оценка:
Здравствуйте, GarryIV, Вы писали:

благодарю за ответ.
Смысл первого вопроса не в чистоте кода, а в разнице использования
final private Object lock = new Object();
final private List<...> collection = new LinkedList<>();
synchronized(this.lock) { collection.add(); }
и варианте без "Object lock", когда объектом синхронизации выступает сама коллекция.

pva>>Правильно ли я понимаю что для синхронизированных коллекций коллекция будет лочится на все время цикла для обеспечения целостности итераторов?

GIV>нет не будет
хм.. то есть, вполне реально огрести рантайм эксепшн о том что идет доступ к измененной коллекции из-за инвалидации итераторов?

GIV>оно конечно решит проблему ( как и synchronized (this.numbers) )

GIV>но в жабе есть конкурентные коллекции же примерно 100 лет как.
Да я как-то проспал революцию. А последний раз, когда я заглядывал в рукводоства по стандартным конкурентным коллекциям, там отсутствовали то ли очереди, то ли еще какие-то стандартные коллекции.
Кстати, в конкурентных коллекциях нет проблем с классическими циклами (типа инвалидации как в вопросе выше)?
И помнится там что-то мудрили с пайпингом, навроде Collection.forEach(...). Хотя может это не из той оперы.

Most concurrent Collection implementations ... in that their Iterators and Spliterators provide weakly consistent rather than fast-fail traversal...

newbie
Отредактировано 25.10.2023 17:25 pva . Предыдущая версия . Еще …
Отредактировано 25.10.2023 17:24 pva . Предыдущая версия .
Re[3]: Вопрос по synchronized
От: · Великобритания  
Дата: 26.10.23 08:08
Оценка:
Здравствуйте, pva, Вы писали:

pva> Да я как-то проспал революцию.

Ещё одну революцию проспал с Project Loom.

the team’s advice is to replace the use of the synchronized block with Java’s ReentrantLock

https://neiljbrown.com/2022/07/23/preparing-for-java-virtual-threads/
avalon/3.0.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[4]: Вопрос по synchronized
От: pva  
Дата: 26.10.23 10:19
Оценка:
Здравствуйте, ·, Вы писали:

pva>> Да я как-то проспал революцию.

·>Ещё одну революцию проспал с Project Loom.
·>

the team’s advice is to replace the use of the synchronized block with Java’s ReentrantLock

·>https://neiljbrown.com/2022/07/23/preparing-for-java-virtual-threads/
Да я вообще ретроград и джава — мое побочное "увлечение". Я на ней пишу в стиле Си с классами.
А уж заглядывать чего там завезли после 8 версии вообще боюсь. Я как-то сунулся, но огреб проблем с пермишенами в модулях при попытке использования криптографии и забил.
newbie
Re: Вопрос по synchronized
От: vsb Казахстан  
Дата: 26.10.23 11:31
Оценка:
Ничего страшного в этом коде нет, но в целом synchronized в современном коде лучше заменять на Lock-и.

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

В целом это тоже спорный класс и я бы не советовал его использовать. Лучше использовать обычный List и самому блокировки вставлять где надо. Или использовать уже полноценную коллекцию для многопоточности.
Отредактировано 26.10.2023 11:35 vsb . Предыдущая версия . Еще …
Отредактировано 26.10.2023 11:33 vsb . Предыдущая версия .
Отредактировано 26.10.2023 11:32 vsb . Предыдущая версия .
Re[2]: Вопрос по synchronized
От: pva  
Дата: 26.10.23 11:46
Оценка:
Здравствуйте, vsb, Вы писали:

vsb>Ничего страшного в этом коде нет, но в целом synchronized в современном коде лучше заменять на Lock-и.

Други, вы советуете прекрасные решения из java 18+, но я хотел бы заметить, что android до версии 13 (sdk 33) поддерживает не выше java 11, и только 14й (sdk 34) будет поддерживать java 17.
Впрочем, положив руку на сердце, мне java 8 хватает с головой. Разве что хотелось бы "var" из версий повыше.
newbie
Re[3]: Вопрос по synchronized
От: vsb Казахстан  
Дата: 26.10.23 12:05
Оценка: +2
Здравствуйте, pva, Вы писали:

vsb>>Ничего страшного в этом коде нет, но в целом synchronized в современном коде лучше заменять на Lock-и.

pva>Други, вы советуете прекрасные решения из java 18+, но я хотел бы заметить, что android до версии 13 (sdk 33) поддерживает не выше java 11, и только 14й (sdk 34) будет поддерживать java 17.
pva>Впрочем, положив руку на сердце, мне java 8 хватает с головой. Разве что хотелось бы "var" из версий повыше.

Я про ReentrantLock, он с Java 5 доступен.

Повторюсь, это мелочь и совсем не обязательно.
Отредактировано 26.10.2023 12:06 vsb . Предыдущая версия .
Re[4]: Вопрос по synchronized
От: pva  
Дата: 26.10.23 12:19
Оценка:
Здравствуйте, vsb, Вы писали:

vsb>Я про ReentrantLock, он с Java 5 доступен.

Ага, и правда. В хедере просто гугл выдает ссылку на sdk 18, а я не глянул Since: 1.5. Но, как по мне, практически бесполезная штука если вам не нужен tryLock.
synchronized уже является reentrant + ко всему прочему он scoped. А ReentrantLock, насколько я вижу, требует явного unlock.
newbie
Re[2]: Вопрос по synchronized
От: Aleksei_Lekomtsev  
Дата: 26.10.23 14:11
Оценка:
GIV>numbers не публичный так что если ты не отдаешь его наружу (а ты не должен) то нет проблем (в том числе и со стороны "руководств").

А какие "side effects" могут возникнуть если можно отдавать numbers наружу?
Например, кто может начать add/get снаружи в numbers без synchronized (this.numbers)?
Re[3]: Вопрос по synchronized
От: pva  
Дата: 26.10.23 17:12
Оценка:
Здравствуйте, Aleksei_Lekomtsev, Вы писали:

GIV>>numbers не публичный так что если ты не отдаешь его наружу (а ты не должен) то нет проблем (в том числе и со стороны "руководств").

A_L>А какие "side effects" могут возникнуть если можно отдавать numbers наружу?
A_L>Например, кто может начать add/get снаружи в numbers без synchronized (this.numbers)?
Может, конечно. Посыпятся эксепшны при одновременном доступе + изменении коллекции.
newbie
Re[3]: Вопрос по synchronized
От: GarryIV  
Дата: 26.10.23 18:05
Оценка:
Здравствуйте, Aleksei_Lekomtsev, Вы писали:


GIV>>numbers не публичный так что если ты не отдаешь его наружу (а ты не должен) то нет проблем (в том числе и со стороны "руководств").


A_L>А какие "side effects" могут возникнуть если можно отдавать numbers наружу?

даже думать не буду, любые

A_L>Например, кто может начать add/get снаружи в numbers без synchronized (this.numbers)?

я почем знаю кто? и знать не хочу, нельзя такое отдавать. иммутабельное — можно (при условии сейф паблишинга), треад сейф структуры — можно, линкед лист — нельзя.
его и в однопоточной проге лучше не отдавать...
WBR, Igor Evgrafov
Re[2]: Вопрос по synchronized
От: GarryIV  
Дата: 26.10.23 18:09
Оценка:
Здравствуйте, vsb, Вы писали:

vsb>Ничего страшного в этом коде нет, но в целом synchronized в современном коде лучше заменять на Lock-и.

чем Lock лучше?
WBR, Igor Evgrafov
Re[4]: Вопрос по synchronized
От: Aleksei_Lekomtsev  
Дата: 26.10.23 18:21
Оценка:
Здравствуйте, GarryIV, Вы писали:

GIV>Здравствуйте, Aleksei_Lekomtsev, Вы писали:



GIV>>>numbers не публичный так что если ты не отдаешь его наружу (а ты не должен) то нет проблем (в том числе и со стороны "руководств").


A_L>>А какие "side effects" могут возникнуть если можно отдавать numbers наружу?

GIV>даже думать не буду, любые

A_L>>Например, кто может начать add/get снаружи в numbers без synchronized (this.numbers)?

GIV>я почем знаю кто? и знать не хочу, нельзя такое отдавать. иммутабельное — можно (при условии сейф паблишинга), треад сейф структуры — можно, линкед лист — нельзя.
GIV>его и в однопоточной проге лучше не отдавать...

*Например, кто может начать add/get снаружи в numbers без synchronized (this.numbers)?
Ошибся, прошу прощения. Хотел написать — кто-то может начать add/get снаружи в numbers без synchronized (this.numbers)?
Отредактировано 26.10.2023 18:25 Aleksei_Lekomtsev . Предыдущая версия .
Re[3]: Вопрос по synchronized
От: Aleksei_Lekomtsev  
Дата: 26.10.23 18:24
Оценка:
Здравствуйте, GarryIV, Вы писали:

GIV>Здравствуйте, vsb, Вы писали:


vsb>>Ничего страшного в этом коде нет, но в целом synchronized в современном коде лучше заменять на Lock-и.

GIV>чем Lock лучше?

Возможно потому что можно использовать tryLock
Re[3]: Вопрос по synchronized
От: vsb Казахстан  
Дата: 26.10.23 20:17
Оценка:
Здравствуйте, GarryIV, Вы писали:

vsb>>Ничего страшного в этом коде нет, но в целом synchronized в современном коде лучше заменять на Lock-и.

GIV>чем Lock лучше?

1. У виртуальных потоков из 21 жавы с synchronized на текущий момент проблемы. Предположительно будут решены в будущем.

2. Если синхронизироваться по публично доступному объекту, есть гипотетическая возможность того, что кто-то тоже захочет по нему синхронизироваться.
Re[4]: Вопрос по synchronized
От: GarryIV  
Дата: 26.10.23 21:15
Оценка:
Здравствуйте, vsb, Вы писали:

vvsb>1. У виртуальных потоков из 21 жавы с synchronized на текущий момент проблемы. Предположительно будут решены в будущем.

есть такой момент
кстати пробовал кто?
а то я на 17 + котдин корутинах, особо без надобности.
WBR, Igor Evgrafov
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.