Здравствуйте, есть похожие вопросы, но я не смог найти ответ, который помог бы мне.В весеннем загрузочном приложении у меня есть класс Service для перевода денег между счетами, где я использую детальную блокировку.Потоки заблокируются, если они принадлежат одному аккаунту.
@Service
public class AccountServiceImpl implements AccountService {
static final HashMap<Long, ReentrantLock> locks = new HashMap<Long, ReentrantLock>();
private ReentrantLock getLock(Long id) {
synchronized (locks) {
ReentrantLock lock = locks.get(id);
if (lock == null) {
lock = new ReentrantLock();
locks.put(id, lock);
}
return lock;
}
}
}
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public List<Transaction> transferMoney(Long sourceAccountId, Long targetAccountId, Currency currency, BigDecimal amount) {
Lock lock = getLock(sourceAccountId);
try {
lock.lock();
Balance balance = getBalance(sourceAccountId, currency);
System.out.println("BALANCE BEFORE TRANSFER " + balance.getBalance());
//createTransactions here using transactionService.create(transactions)
accountRepository.refresh(accountRepository.findOne(sourceAccountId))
balance = getBalance(sourceAccountId, currency);
System.out.println("BALANCE AFTER TRANSFER " + balance.getBalance());
return transactions;
}finally{
lock.unlock()
}
}
В основном это работает как положено, за исключением случаев, когда я отправляю несколько параллельных запросов, используя apache jmeter.если я отправляю несколько запросов на перевод 100 USD со счета на 1000 балансов, выводит консоль примерно так:
БАЛАНС ДО ПЕРЕДАЧИ 1000БАЛАНС ПОСЛЕ ПЕРЕДАЧИ 900БАЛАНС ДО ПЕРЕДАЧИ 1000БАЛАНС ПОСЛЕ ПЕРЕДАЧИ 900БАЛАНС ДО ПЕРЕДАЧИ 900БАЛАНС ПОСЛЕ ПЕРЕДАЧИ 800БАЛАНС ДО ПЕРЕДАЧИ 800БАЛАНС ПОСЛЕ ПЕРЕДАЧИ 700БАЛАНС ДО ПЕРЕДАЧИ 700БАЛАНС ПОСЛЕ ПЕРЕДАЧИ 600БАЛАНС ДО ПЕРЕДАЧИ 700БАЛАНС ПОСЛЕ ПЕРЕДАЧИ 600
, поэтому он в основном работает правильно, но в определенные моменты он не получает обновленных балансов.До сих пор я экспериментировал со всем, размножением и изоляциями.Создание транзакций вручную и их выполнение до того, как поток снимет блокировку.Ничто не похоже на работу.До того, как я использовал
Propagation.REQUIRES_NEW
консольный вывод всегда был
БАЛАНС ДО ПЕРЕДАЧИ 1000БАЛАНС ПОСЛЕ ПЕРЕДАЧИ 900
Теперь это иногда работает, иногда нет.Это не соответствует.
Метод Get Balance обновляет учетную запись с помощью:
accountRepository.refresh ()
и TransactionsService.createTransactions также аннотируется с помощью Propagation.REQUIRES_NEW. Так что любой можетскажите, почему это не работает?По крайней мере, направь меня в правильном направлении.
спасибо
РЕДАКТИРОВАТЬ: , если из БД считываются недостаточно четкие данные.используя пружину jpa.