Как стать автором
Обновить

Комментарии 24

Не разрабатываю на Kotlin, но насколько я понимаю корутины могут использовать один и тот же поток. А синхронизация с помощью synchronize блока или метода обладает reentrance свойством, то есть один и тот же поток может заходить в synchronize блок, не снимая блокировку. А вот мютексы таким свойством не обладают.

корутины могут использовать один и тот же поток

Могут один, а могут и разные. Мало того, корутина может "проснуться" не в том потоке, где засыпала.

переведена статья о том, что синхронизация jvm уровня просто НЕ работает в корутинах (без объяснения, чем кооперативная многозадачность отличается от принудительной). Переводчик зачем-то добавил, что "синхронизацию" лучше использовать только при отсутствии точек останова. Сразу вопрос — если она (synchronized секция) не работает вообще, то....???? Либо я не понял статью, либо переводчик. И да, "синхронизация" — это, в том числе, и мьютекс.

Сразу вопрос — если она (synchronized секция) не работает вообще,

Откуда вы такое взяли? Она вполне себе работает, если корутина не саспендится внутри неё.


И да, "синхронизация" — это, в том числе, и мьютекс.

Речь про конкретные synchronization и котлиновский Mutex для корутин

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

Чисто формально — всё работает ровно так, как оно реализовано. Т.е. это не баг и не UB, а особенности реализации. То, что компилятор ругается на suspension point внутри блока synchronized — это скорее костыль, поддерживающий… А вот что? Недостаточно подробную документацию и нежелание разработчиков вникать в детали?


И даже, наверное, можно придумать разумное применение такому поведению. Но я тоже полностью согласен, что получилось мега-неочевидно и допускать компиляцию подобного не желательно. В крайнем случае, если кому прям вот очень надо — отдать на откуп опциям компилятора.

Нда. Как можно было изобретая корутины, сломать семантику synchronized в языке. Она же в языке, и не должна зависеть от способа реализации concurrency, вытесняющая там многопоточность или кооперативная. А по факту mutex-ы, которые отдельные объекты, как раз и работают с корутинами, встроенными в язык, а synchronized нет. Это прямо провал какой-то.
Будем надеяться разработчики loom в Java такой фигни не сделают.

Это только кажется, что она в языке — а на самом деле там ещё и JVM сильно старается. Разумеется, исправить JVM разработчики Kotlin не могут...

Мне кажется все равно можно было что-нибудь придумать, например поскольку это аннотация — дополнительно обернуть synchronized блок от JVM в mutex. Не уверен что так сработает.

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


В котлине должен быть аналог SemaphoreSlim.WaitAsync() из .net, который решает проблемы критических секций в асинхронном коде.

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

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

Например, потому что они ортогональны — одна предназначена для I/O-bound задач, а вторая — для cpu-bound, они имеют разную природу и разные способы управления. Операции, являющиеся синхронизирующими для одной многозадачности могут либо вообще никак не воздействовать на другую, либо наоборот вызывать в ней дедлок.


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


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

Способы управления может и разные, но ни на один из них программист влияния не имеет. Потоками управляет операционная система, корутинами виртуальная машина. Для cpu-bound задач надо просто не запускать корутин, которые сильно нагружают процессор, больше чем ядер в процессоре, вот и все. Потоки на самом деле нафик не нужны, достаточно корутин. Потоки просто оставили для совместимости с Java видимо.

Номинально в котлине нет примитивов синхронизации на уровне языка. Аннотация не работает, synchronized с лямбдой — работает ок. Достаточно компиляторную магию к аннотации применить, и станет ок.

Эта аннотация сделана именно что для совместимости с джавой и делает ровно одну вещь — в генерируемом для JVM таргета коде добавляет к методу ключевое слово.
Для всего остального в котлине и так есть как минимум 4 способа синхронизации с помощью родных для него инструментов

Ох уж эти переименованные картинки с подписями и прочий "мемасный постмодерн"...

Не понял, а зачем делать функцию, которая не должна разрываться разрываемой? То есть, сначала мы делаем её synchronized, а потом делаем так, что она не синхронизирована. Зачем???

ну, оригинальная статья не говорит о том, что не надо саспендится в synchronized секции — это уже придумал переводчик. Статья про то, что привычные жависту примитивы синхронизации в контексте корутин не работают так, как ожидается жуниорами. То есть про то, что надо пользоваться другими средствами. А так совершенно верно — делать функцию suspend без явного разрыва имеет смысл только если разрыв ожидается неявно в одном из вызовов внутри.

ну, оригинальная статья не говорит о том, что не надо саспендится в synchronized секции — это уже придумал переводчик.

Я бы попросил вас подтверждать обвинения фактами. Перевод практически дословен, от и до. От меня тут только то, что в секции "от переводчика".

это факт — именно это и написано в "от переводчика", а в переводе этого нет.

Инертность мышления, стремление мозга действовать по накатанной. Предположим: спринг с webflux на колтине. Всё от начала и до конца suspend — ну "по красоте" же. И вдруг где-то нужна синхронизация и рука на автомате тянется писать @Synchronized.

Елизаров говорил давно, вроде даже в этом же видосе который в посте, что delay не останавливает поток, а вот Thread.sleep внутри корутины остановит. Понятно, что это будет работать от случая, так как не ясно на каком потоке какая корутина будет работать, но все же. Ещё вопрос в использовании общего состояния в параллельном коде. Функциональный подход решает данный вопрос, если, конечно, нет критической необходимости делать общее состояние
Зарегистрируйтесь на Хабре, чтобы оставить комментарий