Locking issue : needs some brainstorming suggestions
I have server service which releases the table database if a certain criterian is satisfied. It looks like this
public static void autoUnloadDbTable(final Configuration conf) {
final String mKey = getMapKey(conf);
final Table table = TABLES.get(mKey);
if (table != null) {
dblock.getLock().lock();
table.instance.dispose();
TABLES.remove(mKey);.....(2)
}
//here release lock when done...
}
But there is another operation which can run sideways when the above function is being executed
public Table getTableLocked(final Lock lock) throws FactFinderException {
boolean loadTable = true;
// Get the current table instance
Table table = TABLES.get(mapKey);
// .....(1)
if (table != null) {
//do something
}
if (loadTable) table = loadTableLocked(table);
// lock the table, so the instance don't gets replaced
if (lock != null) lock.lock();
return table.instance;
}
At (1) i need to put something because if one thread is executing the code at (2) and the other thread is at thread (2) which already have a table object but as (2) is executing so it will delete the table object and then everything beyond (1) will not have a开发者_开发技巧 correct value....any suggestions please...??
You probably want a read/write lock around TABLES. Acquire a read lock before you do TABLES.get(...) to use something from tables , and acquire a write lock before you do TABLES.get(...) to delete from it.
The alternative is to have a lock per table. After a TABLES.get(...) acquire the Table specific lock, then make sure the Table is still in TABLES, then perform your action with the lock. This Table specific lock can be a read/write lock as well, then only the code wishing to delete will acquire a write lock. This gets complicated when you try to add to TABLES, you will need to be clever, and probably use a ConcurrentMap for TABLES, and use putIfAbsent.
Why not just use a ConcurrentHashMap, it is more efficient.
I think you can utilize ConcurrentHashMap's lock mechanism and remove your own. So remove first in section 1:
public static void autoUnloadDbTable(final Configuration conf) {
final String mKey = getMapKey(conf);
final Table table = TABLES.remove(mKey);
if (table != null) {
table.instance.dispose();
}
}
Section 2 is like this:
public Table getTableLocked(final Lock lock) throws FactFinderException {
boolean loadTable = true;
// Get the current table instance
Table table = TABLES.get(mapKey);
// .....(1)
if (table != null) {
//do something
}
if (loadTable) table = loadTableLocked(table);
return table.instance;
}
}
Based on the comments you could consider wrapping your tables:
public class LockableTable {
public Table table;
public ReadWriteLock lock;
public LockableTable(Table t){
table = t;
lock = ....
}
}
Then when you want to delete the table you take the myLocakbleTable.lock.writeLock().lock()
. Rest of the time when you are reading from the table you take the myLockableTable.lock.readLock().lock()
精彩评论