开发者

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()

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜