Может быть простой способ позволить вашей базе данных позаботиться об этом за вас. Я по общему признанию слаб в знании, когда дело доходит до баз данных. Вместо этого, вот подход, который включает в себя создание индивидуальной блокировки для каждого имени ключа. Существует один репозиторий, который управляет созданием / уничтожением отдельных блокировок, для которого требуется блокировка «один для всего приложения», но он удерживает эту блокировку только во время обнаружения, создания или уничтожения отдельной блокировки имени ключа , Блокировка, которая удерживается для фактической операции базы данных, является исключительной для имени ключа, используемого в этой операции.
Класс KeyLock используется для предотвращения одновременных операций базы данных с одним именем ключа.
package KeyLocks;
import java.util.concurrent.locks.Lock;
public class KeyLock
{
private final KeyLockManager keyLockManager;
private final String keyName;
private final Lock lock;
KeyLock(KeyLockManager keyLockManager, String keyName, Lock lock)
{
this.keyLockManager = keyLockManager;
this.keyName = keyName;
this.lock = lock;
}
@Override
protected void finalize()
{
release();
}
public void release()
{
keyLockManager.releaseLock(keyName);
}
public void lock()
{
lock.lock();
}
public void unlock()
{
lock.unlock();
}
}
Класс KeyLockManager - это хранилище, отвечающее за время жизни блокировки ключа.
package KeyLocks;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class KeyLockManager
{
private class LockEntry
{
int acquisitionCount = 0;
final Lock lock = new ReentrantLock();
}
private final Map<String, LockEntry> locks = new HashMap<String, LockEntry>();
private final Object mutex = new Object();
public KeyLock getLock(String keyName)
{
synchronized (mutex)
{
LockEntry lockEntry = locks.get(keyName);
if (lockEntry == null)
{
lockEntry = new LockEntry();
locks.put(keyName, lockEntry);
}
lockEntry.acquisitionCount++;
return new KeyLock(this, keyName, lockEntry.lock);
}
}
void releaseLock(String keyName)
{
synchronized (mutex)
{
LockEntry lockEntry = locks.get(keyName);
lockEntry.acquisitionCount--;
if (lockEntry.acquisitionCount == 0)
{
locks.remove(keyName);
}
}
}
}
Вот пример того, как вы бы использовали блокировку клавиш.
package test;
import KeyLocks.KeyLock;
import KeyLocks.KeyLockManager;
public class Main
{
private static final String KEY_NAME = "TEST_KEY";
public static void main(String[] args)
{
final KeyLockManager keyLockManager = new KeyLockManager();
KeyLock keyLock = null;
try
{
keyLock = keyLockManager.getLock(KEY_NAME);
keyLock.lock();
try
{
// Do database operation on the data with the specified key name
}
finally
{
keyLock.unlock();
}
}
finally
{
if (keyLock != null)
{
keyLock.release();
}
}
}
}