Модераторы: LSD, AntonSaburov
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Синхронизация потоков в spring mvc 
V
    Опции темы
toxx
Дата 17.10.2014, 21:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 653
Регистрация: 4.3.2009
Где: НН

Репутация: нет
Всего: 13



Добрый день.

Хочу задать вопрос относительно синхронизации потоков в spring mvc и как такое решается, 
потому что не уверен в оптимальности своего решения.

Используемые технологии : Spring mvc, Hibernate.

Происходит регистрация номера(Одновременно операцию выполняют несколько пользователей), который генерируется на основе того, что сейчас есть в БД.
Ниже постараюсь описать схематично алгоритм и привести немного кода.

Сценарий такой:
1. В контроллере через сервис регистрируется новый номер
2. Берется максимальный номер последней зарегистрированной сущности
3. Этот номер используется для создания новой(схематично новыйНомер = номерПредыдущий + 1)
4. Номер должен быть сгенерирован уникальный

Код

@Service
public class ServiceImpl implements Service {

    @Override
    @Transactional
    public void register(...) {
         createNumber(...);
    }
    
    @Override
    public void createNumber(...) {
            .....
            Integer maxNumber = findMaxNumber(); // Ищется максимальный номер(без транзакции)
            entity.setNumber(maxNumber + 1);
            dao.update(entity); // update делается через hql
    }
}


Проблема возникает при одновременном выполнении операции регистрации.
Т.е. два пользователя одновременно решили сгенерировать номер, в результате чего метод
findMaxNumber возвращает один и тот же номер последней зарегистрированной сущности.
(Происходит это потому что сущность довольно тяжелая и не успевает сохраниться до того как другой поток вызывает findMaxNumber)
В результате сохраняются одинаковые номера в БД.

Вариант решения проблемы - сделать сервис синхронизации этой операции.

Код

@Service
public class SyncService {

    @Autowired
    private Service service;

    private Lock lock = new ReentrantLock();

    public void register(...) {
            try {
                lock.lock();
                service.register(...);
            } finally {
                lock.unlock();
            }
    }
}


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

Спасибо.
PM MAIL   Вверх
d_k
Дата 20.10.2014, 07:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 76
Регистрация: 20.7.2004

Репутация: 1
Всего: 1



А чем сиквенсы на БД не устраивают? Или автоинкремент поля.
PM MAIL   Вверх
toxx
Дата 20.10.2014, 20:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 653
Регистрация: 4.3.2009
Где: НН

Репутация: нет
Всего: 13



d_k
Что вы имеете ввиду под сиквенсами и автоинкрементом? Если вы про это:
Код

entity.setNumber(maxNumber + 1);


То этот код только для примера, на самом деле поле строка и этот maxNumber одно из чисел,
которые участвуют в создании номера.
PM MAIL   Вверх
xoslv
Дата 9.2.2015, 17:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 195
Регистрация: 12.1.2007

Репутация: нет
Всего: нет



Может стоит посмотреть в сторону Singleton? Т.е. объявляете класс как синглетон, а в методе 
Код

createNumber(){}

делаете синхронизацию.
Код

... createNumber(){
         synchronized(ServiceImpl.class){
            Integer maxNumber = findMaxNumber(); // Ищется максимальный номер(без транзакции)
            entity.setNumber(maxNumber + 1);
            dao.update(entity); // update делается через hql
       }
}

Как один из возможных вариантов реализации.
Только я бы наверное ещё добавил каких два метода и локальную переменную, для установки volatile флага.
Но следует учесть, что на высоко нагруженных системах такой метод может вызвать некоторое торможение.
В любом случае, при такой реализации нам нет необходимости думать с какой ДБ мы работаем и как там устроены локи.
--------------------
Не всё то маздай, что синее!
PM MAIL ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java EE (J2EE) и Spring | Следующая тема »


 




[ Время генерации скрипта: 0.0749 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.