Как исправить код, чтобы он работал в многопоточном режиме?
От: Aleksei_Lekomtsev  
Дата: 04.10.23 13:38
Оценка:
@RestController
public class Counter {

  private long counter = 0;
  
  @GetMapping("/increment")
  public long increment() {
    return ++counter;
  }
}

Вместо long думаю можно использовать AtomicLong. Не уверен на счет подойдет ли тут synchronized для increment()...
Re: Как исправить код, чтобы он работал в многопоточном режиме?
От: GarryIV  
Дата: 04.10.23 13:51
Оценка: 1 (1)
Здравствуйте, Aleksei_Lekomtsev, Вы писали:

A_L>Вместо long думаю можно использовать AtomicLong. Не уверен на счет подойдет ли тут synchronized для increment()...

https://foojay.io/today/thread-safe-counter-in-java-a-comprehensive-guide/

LongAdder производительное и простое решение (лучше AtomicLong), а так вариантов много включая synchronized.
WBR, Igor Evgrafov
Re[2]: Как исправить код, чтобы он работал в многопоточном режиме?
От: Aleksei_Lekomtsev  
Дата: 04.10.23 13:57
Оценка:
Здравствуйте, GarryIV, Вы писали:

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


A_L>>Вместо long думаю можно использовать AtomicLong. Не уверен на счет подойдет ли тут synchronized для increment()...

GIV>https://foojay.io/today/thread-safe-counter-in-java-a-comprehensive-guide/

GIV>LongAdder производительное и простое решение (лучше AtomicLong), а так вариантов много включая synchronized.


А если сравнивать AtomicLong и synchronized, есть ли у AtomicLong преимущества, например по performance?

Если использовать synchronized, то при заходе в метод захватывается монитор объекта, т.е. если будут еще методы synchronized, то
они будут ждать очереди пока отработает первый. А если использовать AtomicLong, то вроде как такой сложности не должно возникнуть...
Re[3]: Как исправить код, чтобы он работал в многопоточном режиме?
От: GarryIV  
Дата: 04.10.23 14:18
Оценка: 3 (1)
Здравствуйте, Aleksei_Lekomtsev, Вы писали:

GIV>>LongAdder производительное и простое решение (лучше AtomicLong), а так вариантов много включая synchronized.


A_L>А если сравнивать AtomicLong и synchronized, есть ли у AtomicLong преимущества, например по performance?

да, AtomicLong это CAS — без блокировок, которые тормозные

A_L>Если использовать synchronized, то при заходе в метод захватывается монитор объекта, т.е. если будут еще методы synchronized, то

A_L>они будут ждать очереди пока отработает первый. А если использовать AtomicLong, то вроде как такой сложности не должно возникнуть...
все так
но LongAdder еще лучше
WBR, Igor Evgrafov
Re: Как исправить код, чтобы он работал в многопоточном режиме?
От: Pavel Dvorkin Россия  
Дата: 04.10.23 14:19
Оценка: 1 (1)
Здравствуйте, Aleksei_Lekomtsev, Вы писали:


A_L>
A_L>@RestController
A_L>public class Counter {

A_L>  private long counter = 0;
  
A_L>  @GetMapping("/increment")
A_L>  public long increment() {
A_L>    return ++counter;
A_L>  }
A_L>}
A_L>


Хм. Что-то я не понимаю. Это же инстансное поле класса. С чего ты решил, что экземпляр класса будет один ?

Наверное, нужно static, и тогда AtomicLong
With best regards
Pavel Dvorkin
Re[2]: Как исправить код, чтобы он работал в многопоточном режиме?
От: Aleksei_Lekomtsev  
Дата: 04.10.23 14:24
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

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



A_L>>
A_L>>@RestController
A_L>>public class Counter {

A_L>>  private long counter = 0;
  
A_L>>  @GetMapping("/increment")
A_L>>  public long increment() {
A_L>>    return ++counter;
A_L>>  }
A_L>>}
A_L>>


PD>Хм. Что-то я не понимаю. Это же инстансное поле класса. С чего ты решил, что экземпляр класса будет один ?


PD>Наверное, нужно static, и тогда AtomicLong


Я честно говоря не знаю как Spring работает в этом случае. Т.е. если я правильно понимаю, то если будут 2 get-запроса для
данного endpoint, то Spring создаст 2 threads, которые будут работать с одним и тем же полем counter...но это не точно)
Re[3]: Как исправить код, чтобы он работал в многопоточном режиме?
От: Pavel Dvorkin Россия  
Дата: 04.10.23 14:32
Оценка: 3 (1)
Здравствуйте, Aleksei_Lekomtsev, Вы писали:

A_L>Я честно говоря не знаю как Spring работает в этом случае. Т.е. если я правильно понимаю, то если будут 2 get-запроса для

A_L>данного endpoint, то Spring создаст 2 threads, которые будут работать с одним и тем же полем counter...но это не точно)

Вот здесь обсуждение

https://stackoverflow.com/questions/11508405/are-spring-mvc-controllers-singletons

С одной стороны, пишут, что

Spring controllers are singletons (there is just one instance of each controller per web application) just like servlets.


а с другой

Be aware that they'll only be singletons per context, and that it's entirely possible to have nested contexts when working with Spring web applications, and that by duplicating a package-scan you might end up with multiple instances of the same controller.


Так что я бы поставил static и не парился.
With best regards
Pavel Dvorkin
Re[4]: Как исправить код, чтобы он работал в многопоточном р
От: gyraboo  
Дата: 04.10.23 15:04
Оценка: 1 (1) +1
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Так что я бы поставил static и не парился.


Здесь уже вступаю в игру архитектурные правила. Обычно в контроллерах не размещают бизнес-логику, тем более stateful. Она выносится в сервисный слой или в инкапсулируется DDD-обьектом. Они и отвечают за гарантии, и конфигуряться специально для обеспечения Singleton-логики этих данных. А конфигурить scope контроллера для этого нельзя, это смертный грех архитектуры. Эти рассуждения показывают, что ты не просто сам язык Java Core знаешь, но и знаком с парадигмами энтерпрайз-разработки на джаве.
Отредактировано 04.10.2023 15:06 gyraboo . Предыдущая версия . Еще …
Отредактировано 04.10.2023 15:05 gyraboo . Предыдущая версия .
Re[5]: Как исправить код, чтобы он работал в многопоточном р
От: Aleksei_Lekomtsev  
Дата: 04.10.23 15:09
Оценка:
Здравствуйте, gyraboo, Вы писали:

G>Здравствуйте, Pavel Dvorkin, Вы писали:


PD>>Так что я бы поставил static и не парился.


G>Здесь уже вступаю в игру архитектурные правила. Обычно в контроллерах не размещают бизнес-логику, тем более stateful. Она выносится в сервисный слой или в инкапсулируется DDD-обьектом. Они и отвечают за гарантии, и конфигуряться специально для обеспечения Singleton-логики этих данных. А конфигурить scope контроллера для этого нельзя, это смертный грех архитектуры.


класс со static полем — рассматривает как stateful? stateful к свойству объекта относится?

П.С. Думаю поторопился с вопросом)Если у класса есть поля, то это stateful, если ничего не напутал)
Отредактировано 04.10.2023 15:23 Aleksei_Lekomtsev . Предыдущая версия .
Re[5]: Как исправить код, чтобы он работал в многопоточном р
От: Pavel Dvorkin Россия  
Дата: 04.10.23 15:11
Оценка:
Здравствуйте, gyraboo, Вы писали:

G>Здесь уже вступаю в игру архитектурные правила. Обычно в контроллерах не размещают бизнес-логику, тем более stateful. Она выносится в сервисный слой или в инкапсулируется DDD-обьектом. Они и отвечают за гарантии, и конфигуряться специально для обеспечения Singleton-логики этих данных. А конфигурить scope контроллера для этого нельзя, это смертный грех архитектуры. Эти рассуждения показывают, что ты не просто сам язык Java Core знаешь, но и знаком с парадигмами энтерпрайз-разработки на джаве.


Знаком, не беспокойся ...
Я вообще предпочитаю, чтобы в методе контроллера была одна строчка — вызов метода сервиса.

Но ТС хочет так, вот я и решил выяснить, синглетон он или нет. Как-то раньше не задумывался об этом.
With best regards
Pavel Dvorkin
Re[4]: Как исправить код, чтобы он работал в многопоточном режиме?
От: m2user  
Дата: 04.10.23 18:10
Оценка: +2
GIV>все так
GIV>но LongAdder еще лучше

У LongAdder ведь нет аналога AtomicLong.incrementAndGet, т.е. без доп. синхронизации AtomicLong он в данном случае не заменит.
Re[6]: Как исправить код, чтобы он работал в многопоточном р
От: gyraboo  
Дата: 04.10.23 18:35
Оценка: 1 (1)
Здравствуйте, Aleksei_Lekomtsev, Вы писали:

A_L>класс со static полем — рассматривает как stateful? stateful к свойству объекта относится?


A_L>П.С. Думаю поторопился с вопросом)Если у класса есть поля, то это stateful, если ничего не напутал)


Стейтфул объект конечно если это поле не статик. А если статик, то тут стейтлес объект, но можно сказать что стейтфул класс наверное. Так что прав наверное именно ты.
У контроллера могут быть поля, инжектируемые самим контейнером зависимости, контролируемве им, при этом объект не считается стейтфул. Стейтфул это имеется ввиду именно хранение бизнесового состояния в экземпляре класса.
Re[2]: Как исправить код, чтобы он работал в многопоточном режиме?
От: GarryIV  
Дата: 04.10.23 20:49
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

A_L>>
A_L>>@RestController
A_L>>


PD>Хм. Что-то я не понимаю. Это же инстансное поле класса. С чего ты решил, что экземпляр класса будет один ?


RestController как бы намекает
Но если отвлечься от спринга то все равно статик не нужен.
WBR, Igor Evgrafov
Re: Как исправить код, чтобы он работал в многопоточном режиме?
От: r0nd  
Дата: 05.10.23 00:21
Оценка: 1 (1)
Здравствуйте, Aleksei_Lekomtsev, Вы писали:


AL>Вместо long думаю можно использовать AtomicLong. Не уверен на счет подойдет ли тут synchronized для increment()...


Сразу обращаю внимание, что предложеная архитектура в твоем примере неверная. Счетчик должен быть не на слое представления (не в классе @RestController), а на слое бизнес-логики (@Service/@Component/@Bean). Кроме того, неплохо было бы использовать стандартное Spring-решение на базе Spring Actuator с Metrics, чтобы не городить велосипеды.

В любом случае, техническое (про архитектуру я выше написал) решение может быть любым и по уровню синхронизации (что является объектом синхронизации) и по типу велосипеда, будет ли это решение с AtomicLong или synchronized один фиг это будет работать в рамках только одной ноды/сервера в мульти-потоковом окружении. Но как только решишь распараллелить на контейнеры/виртуалки — то будет попоболь .
...<< Dementor 1.4.3 ✪ Lets Play a Game ⚀⚂⚂⚃⚅>>
Re[5]: Как исправить код, чтобы он работал в многопоточном режиме?
От: GarryIV  
Дата: 05.10.23 08:36
Оценка:
Здравствуйте, m2user, Вы писали:

GIV>>все так

GIV>>но LongAdder еще лучше

M>У LongAdder ведь нет аналога AtomicLong.incrementAndGet, т.е. без доп. синхронизации AtomicLong он в данном случае не заменит.


угу, и получение текущего значения скорее всего убъет всю выгоду
WBR, Igor Evgrafov
Re[6]: Как исправить код, чтобы он работал в многопоточном режиме?
От: · Великобритания  
Дата: 05.10.23 19:14
Оценка:
Здравствуйте, GarryIV, Вы писали:

GIV> M>У LongAdder ведь нет аналога AtomicLong.incrementAndGet, т.е. без доп. синхронизации AtomicLong он в данном случае не заменит.

GIV> угу, и получение текущего значения скорее всего убъет всю выгоду
А если какую-то выгоду и удастся получить, то её никак не будет возможно разглядеть в условиях десятков слоёв спринга и прочего rest.
avalon/3.0.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.