-
1. Re: Locking mechanism
rvansa May 7, 2014 10:38 AM (in response to tomas11)It's no wonder that there are less keys, the set got from the cache is always a copy.
a) Use transactions http://infinispan.org/docs/6.0.x/user_guide/user_guide.html#_configuring_transactions
b) Use atomic operations such as cache.putIfAbsent(...) and cache.replace(...)
-
2. Re: Locking mechanism
mircea.markus May 7, 2014 10:41 AM (in response to tomas11)In between you read the set(line 25) and you write it back (line 30), other thread will update it, and you overwrite that update.
I see two ways for you to handle this:
- Use pessimistic locking: lock the key before reading it and release the lock after writing it. This will guarantee that only one thread updates the value at a time
- Use DeltaAware (or (FineGrained)AtomicHashMap) to update only parts of the map
-
3. Re: Locking mechanism
tomas11 May 7, 2014 11:34 AM (in response to mircea.markus)Thanks for answers.
I use this transaction.
<transaction transactionMode="TRANSACTIONAL" useEagerLocking="true" transactionManagerLookupClass="org.infinispan.transaction.lookup.GenericTransactionManagerLookup"
cacheStopTimeout="30000" lockingMode="PESSIMISTIC" >
<recovery enabled="true"/>
</transaction>
but this does not seem to do a job. Should be this enough to declare it in configuration file or is there need to explicitly call lock in code?
How could atomic operations such as cache.putIfAbsent(...) and cache.replace(...) help me in this case?
-
4. Re: Re: Locking mechanism
rvansa May 9, 2014 2:27 AM (in response to tomas11)1 of 1 people found this helpfulConfiguring transactions is not enough, you have to use them:
TransactionManager tm = cache.getAdvancedCache().getTransactionManager();
tm.begin();
try {
cache.getAdvancedCache().lock(key);
Set<UniqueID> keySet = cache.get(key);
if(keySet == null) {
keySet = new HashSet<>();
}
keySet.add(new UniqueID());
cache.put(key, keySet);
tm.commit();
} catch (Exception e) {
tm.rollback();
}
This could also work with optimistic transactions, but I'd have to enable write skew checks in configuration. But pessimistic transactions are more appropriate here.
As for the atomic operations, you could just do the same as for ConcurrentHashMap:
UniqueID newId = new UniqueID())
for (;;) {
Set<UniqueID> originalSet = cache.get(key);
if (originalSet == null) {
Set<UniqueID> newSet = new HashSet<UniqueID>(Collections.singleton(newId));
if (cache.putIfAbsent(key, newSet) == null) break;
} else {
Set<UniqueID> newSet = new HashSet<UniqueID>(keySet);
newSet.add(new UniqueID());
if (cache.replace(key, keySet, newSet)) break;
}
}