Синхронизировано на объекте экземпляра - PullRequest
0 голосов
/ 26 апреля 2020

У меня есть сервисный метод, который в основном вставляет запись в базу данных. То, что я пытаюсь достичь, это заблокировать кусок кода на основе объекта или его переменной.

Мне нужно заблокировать другие потоки на основе этого идентификатора: rcvTransactionRequest.getPoDistributionId() Я не хочу блокировать все потоки, которые входят в этот метод. В конце я пытаюсь проверить количество, которое не должно быть превышено, что может произойти, если несколько потоков войдут в критическую секцию.

    PoDistPayload poDistPayload = poDistService.getPoDist(rcvTransactionRequest.getPoDistributionId());
    synchronized (poDistPayload) {
        if (!poDistService.isReceivable(poDistPayload, rcvTransactionRequest.getQuantity()))
            throw ebsExceptionFactory.build(1036L, rcvTransactionRequest.getQuantity(), poDistPayload.getReceivableQuantity());

        PoDistRcv poDistRcv = PoDistRcv.of(rcvTransactionRequest);
        poDistRcv.setStatus(Status.TRANSACTION_STARTED);
        poDistRcv = poDistRcvRepository.save(poDistRcv);
        return new BaseTransactionResponse(poDistRcv.getTransactionId(), serialCountPerRequest, poDistRcv.getStatus());
    }

Ответы [ 2 ]

0 голосов
/ 28 апреля 2020

Я решил проблему с помощью полоски гуавы.

0 голосов
/ 26 апреля 2020

Вы можете использовать ConcurrentMap для реализации простой схемы блокировки:

Object newLock=new Object();
Object existingLock;
// Wait until this thread can acquire lock
synchronized(newLock) {
  do {
    existingLock=cMap.putIfAbsent(distributionId,newLock);
    if(existingLock!=null) {
        // Locked by another thread. You can fail immediately, or wait until the lock is released
        synchronized(existingLock) {
          // Need timeout here because lock holder may notify before we wait
          existingLock.wait(timeout);
       }
    }
  } while(existingLock!=null);
  // You have the lock
  // Do work
  // Unlock and notify
  cMap.remove(distributionId,newLock);
  newLock.notify();
}
...