ревьюил тут код свой и возник вопрос по синхронизации:
final private LinkedList<Integer> numbers = new LinkedList<>();
...
synchronized (this.numbers) { // sync on the same instance, w/o special lockthis.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) ...
Здравствуйте, 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 забудь вообще.
благодарю за ответ.
Смысл первого вопроса не в чистоте кода, а в разнице использования
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...
Здравствуйте, ·, Вы писали:
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 версии вообще боюсь. Я как-то сунулся, но огреб проблем с пермишенами в модулях при попытке использования криптографии и забил.
Ничего страшного в этом коде нет, но в целом synchronized в современном коде лучше заменять на Lock-и.
Синхронизации по итератору в synchronizedList нет, поэтому тут юзер должен сам синхронизироваться. В жавадоке в принципе про это почти большими буквами написано. Итерироваться без блокировок по synchronizedList, который может меняться, это просто баг.
В целом это тоже спорный класс и я бы не советовал его использовать. Лучше использовать обычный List и самому блокировки вставлять где надо. Или использовать уже полноценную коллекцию для многопоточности.
Здравствуйте, vsb, Вы писали:
vsb>Ничего страшного в этом коде нет, но в целом synchronized в современном коде лучше заменять на Lock-и.
Други, вы советуете прекрасные решения из java 18+, но я хотел бы заметить, что android до версии 13 (sdk 33) поддерживает не выше java 11, и только 14й (sdk 34) будет поддерживать java 17.
Впрочем, положив руку на сердце, мне java 8 хватает с головой. Разве что хотелось бы "var" из версий повыше.
Здравствуйте, pva, Вы писали:
vsb>>Ничего страшного в этом коде нет, но в целом synchronized в современном коде лучше заменять на Lock-и. pva>Други, вы советуете прекрасные решения из java 18+, но я хотел бы заметить, что android до версии 13 (sdk 33) поддерживает не выше java 11, и только 14й (sdk 34) будет поддерживать java 17. pva>Впрочем, положив руку на сердце, мне java 8 хватает с головой. Разве что хотелось бы "var" из версий повыше.
Здравствуйте, vsb, Вы писали:
vsb>Я про ReentrantLock, он с Java 5 доступен.
Ага, и правда. В хедере просто гугл выдает ссылку на sdk 18, а я не глянул Since: 1.5. Но, как по мне, практически бесполезная штука если вам не нужен tryLock.
synchronized уже является reentrant + ко всему прочему он scoped. А ReentrantLock, насколько я вижу, требует явного unlock.
GIV>numbers не публичный так что если ты не отдаешь его наружу (а ты не должен) то нет проблем (в том числе и со стороны "руководств").
А какие "side effects" могут возникнуть если можно отдавать numbers наружу?
Например, кто может начать add/get снаружи в numbers без synchronized (this.numbers)?
Здравствуйте, Aleksei_Lekomtsev, Вы писали:
GIV>>numbers не публичный так что если ты не отдаешь его наружу (а ты не должен) то нет проблем (в том числе и со стороны "руководств"). A_L>А какие "side effects" могут возникнуть если можно отдавать numbers наружу? A_L>Например, кто может начать add/get снаружи в numbers без synchronized (this.numbers)?
Может, конечно. Посыпятся эксепшны при одновременном доступе + изменении коллекции.
GIV>>numbers не публичный так что если ты не отдаешь его наружу (а ты не должен) то нет проблем (в том числе и со стороны "руководств").
A_L>А какие "side effects" могут возникнуть если можно отдавать numbers наружу?
даже думать не буду, любые
A_L>Например, кто может начать add/get снаружи в numbers без synchronized (this.numbers)?
я почем знаю кто? и знать не хочу, нельзя такое отдавать. иммутабельное — можно (при условии сейф паблишинга), треад сейф структуры — можно, линкед лист — нельзя.
его и в однопоточной проге лучше не отдавать...
Здравствуйте, vsb, Вы писали:
vsb>Ничего страшного в этом коде нет, но в целом synchronized в современном коде лучше заменять на Lock-и.
чем Lock лучше?
Здравствуйте, 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)?
Здравствуйте, GarryIV, Вы писали:
GIV>Здравствуйте, vsb, Вы писали:
vsb>>Ничего страшного в этом коде нет, но в целом synchronized в современном коде лучше заменять на Lock-и. GIV>чем Lock лучше?
Здравствуйте, GarryIV, Вы писали:
vsb>>Ничего страшного в этом коде нет, но в целом synchronized в современном коде лучше заменять на Lock-и. GIV>чем Lock лучше?
1. У виртуальных потоков из 21 жавы с synchronized на текущий момент проблемы. Предположительно будут решены в будущем.
2. Если синхронизироваться по публично доступному объекту, есть гипотетическая возможность того, что кто-то тоже захочет по нему синхронизироваться.
Здравствуйте, vsb, Вы писали:
vvsb>1. У виртуальных потоков из 21 жавы с synchronized на текущий момент проблемы. Предположительно будут решены в будущем.
есть такой момент
кстати пробовал кто?
а то я на 17 + котдин корутинах, особо без надобности.