Проблема с блокировкой: нужны предложения для мозгового штурма - PullRequest
1 голос
/ 24 марта 2011

У меня есть серверная служба, которая освобождает базу данных таблиц, если удовлетворяется определенный критерий.Это выглядит так:

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...
}

Но есть другая операция, которая может выполняться вбок при выполнении вышеуказанной функции

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;
}

В (1) мне нужно что-то положить, потому что еслипоток выполняет код в (2), а другой поток - в потоке (2), у которого уже есть объект таблицы, но, поскольку (2) выполняется, поэтому он удалит объект таблицы, а затем все, что находится за пределами (1), не будет иметьправильное значение .... любые предложения, пожалуйста ... ??

Ответы [ 3 ]

0 голосов
/ 24 марта 2011

Вы, вероятно, хотите блокировку чтения / записи вокруг TABLES.Получите блокировку чтения перед тем, как выполнить TABLES.get (...), чтобы использовать что-то из таблиц, и получите блокировку записи, прежде чем выполнять TABLES.get (...), чтобы удалить из него.это иметь блокировку на стол.После того, как TABLES.get (...) получит блокировку, специфичную для таблицы, убедитесь, что таблица все еще находится в TABLES, затем выполните действие с блокировкой.Эта специфичная для таблицы блокировка также может быть блокировкой чтения / записи, тогда только код, желающий удалить, получит блокировку записи.Это становится сложным, когда вы пытаетесь добавить в TABLES, вам нужно быть умным, и, вероятно, использовать ConcurrentMap для TABLES и использовать putIfAbsent.

0 голосов
/ 24 марта 2011

Почему бы просто не использовать ConcurrentHashMap, он более эффективен.

Я думаю, что вы можете использовать механизм блокировки ConcurrentHashMap и удалить свой собственный.Поэтому сначала удалите в разделе 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();
    }
}

Раздел 2 выглядит так:

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;
}

}

0 голосов
/ 24 марта 2011

Основываясь на комментариях, вы можете рассмотреть упаковку ваших таблиц:

public class LockableTable {
 public Table table;
 public ReadWriteLock lock;
 public LockableTable(Table t){
   table = t;
   lock = ....
 }
}

Затем, когда вы хотите удалить таблицу, вы берете myLocakbleTable.lock.writeLock().lock().В остальное время, когда вы читаете со стола, вы принимаете myLockableTable.lock.readLock().lock()

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...