What is the best way to prevent concurrent update of one record in a key-value set without locking the entire set? Semantically, I\'m looking for some kind of locking by a k
I've written a class that can lock on any key dynamically.
It uses a static CuncurrentHashMap. But if no lock is used, the map is empty. The syntax can be confusing as a new object us created based on the key.
It cleans up the lock, if not used, on unlock.
There's a guarantee that any two DynamicKeyLock that were created based on two equal/hascode keys, they'll be mutually locked.
See implementation for Java 8, Java 6 and a small test.
Java 8:
public class DynamicKeyLock implements Lock
{
private final static ConcurrentHashMap
Java 6:
public class DynamicKeyLock implements Lock
{
private final static ConcurrentHashMap
Test:
public class DynamicKeyLockTest
{
@Test
public void testDifferentKeysDontLock() throws InterruptedException
{
DynamicKeyLock lock = new DynamicKeyLock<>(new Object());
lock.lock();
AtomicBoolean anotherThreadWasExecuted = new AtomicBoolean(false);
try
{
new Thread(() ->
{
DynamicKeyLock anotherLock = new DynamicKeyLock<>(new Object());
anotherLock.lock();
try
{
anotherThreadWasExecuted.set(true);
}
finally
{
anotherLock.unlock();
}
}).start();
Thread.sleep(100);
}
finally
{
Assert.assertTrue(anotherThreadWasExecuted.get());
lock.unlock();
}
}
@Test
public void testSameKeysLock() throws InterruptedException
{
Object key = new Object();
DynamicKeyLock lock = new DynamicKeyLock<>(key);
lock.lock();
AtomicBoolean anotherThreadWasExecuted = new AtomicBoolean(false);
try
{
new Thread(() ->
{
DynamicKeyLock anotherLock = new DynamicKeyLock<>(key);
anotherLock.lock();
try
{
anotherThreadWasExecuted.set(true);
}
finally
{
anotherLock.unlock();
}
}).start();
Thread.sleep(100);
}
finally
{
Assert.assertFalse(anotherThreadWasExecuted.get());
lock.unlock();
}
}
}