LINUX.ORG.RU

Пул блокировок?


0

0

Есть вот такой интересный код:

  private QueryResult _getQueryResult(Statement statement) throws Exception {
    QueryResult res = null;
    synchronized (getLock(statement)) {
      synchronized(qrcache) {
        res = qrcache.get(statement);
      }
      if(res == null){
        res = db.select(statement, 0, -1);
        synchronized (qrcache) {
          qrcache.put(statement, res);
        }
      }
    }
    return res;
  }

  synchronized Object getLock(Object src){
    int hash = (src == null)? 0 : src.hashCode();
    int lockIndex = Math.abs(hash % locks.length);
    Object lock = locks[lockIndex];
    if(lock == null){
      locks[lockIndex] = lock = new Object();
    }
    return lock;
  }

qrcache - хеш мап кеша, не thread safe

Вопрос: Сколько причин может быть не писать так и почему. Дело в том что интуиция говорит что тут зарыта большая задница, но я ее не могу найти.

★★☆

Да, затея какая, дело в том что

res = db.select(statement, 0, -1);

может выполнятся очень долго, то заблокирует все потоки на несколько минут, а тут блокируется только потоки имеющие хеш код statementa идиентичный по модулю. Как итог загрузка приложения происходит шустрее, а работу все равно нельзя начать пока все не загрузится.

wfrr ★★☆
() автор топика

ok тогда посоветуйте форум где могут ответить на такой вопрос 8)

wfrr ★★☆
() автор топика
Ответ на: комментарий от wfrr

Имхо разруливать блокировки нужно на уровне дизайна БД и изоляции транзакций а не вручную в приложении.

Legioner ★★★★★
()

А нафига двойная блокировка в самом начале?

Из оптимистичного предположения, что занесение данных происходит гораздо реже, чем их чтение: (разменяли одну блокировку на дополнительное чтение кеша)

synchronized (qrcache) {
  res = qrcache.get (statement);
}

if (res == null) {

  synchronized (getLock (statement)) {

    synchronized (qrcache) {
      res = qrcache.get (statement);
    }

    if (res == null) {

      res = db.select (statement, 0, -1);

      synchronized (qrcache) {
        qrcache.put (statement, res);
      }
    }
  }
}

return res;
dave ★★★★★
()

Если все возможные стейтменты независимы (а оно, очевидно, так и есть), то, имхо, задницы не будет. Будет неоптимальность.

Во-первых, уверен ли ты, что параллельное выполнение запросов быстрее последовательного? Это не всегда так.

Во-вторых, если п.1, то может лучше не заморачиваться и выполнять все запросы одновременно?

В третьих, лок на чтение и на запись кеша одинаковый. А ведь операции чтения запросто могут быть thread-safe, упускаешь сотни скорости.

legolegs ★★★★★
()
Ответ на: комментарий от legolegs

>Во-вторых

Тфу, запутался. Возня с локами исключительно ради того, чтобы кеш не сломать. Пункт 2 аннулируется.

legolegs ★★★★★
()
Ответ на: комментарий от legolegs

Нагуглил кучу книг, как итог переписал на FitureTask, кучеряво, код щас не смогу показать, но почти содран с Memorizer из одной книги, за исключением массива блокировок он остался, так как мап кеша не имеет атомарной операции putIfAbsent.

wfrr ★★☆
() автор топика
Ответ на: комментарий от Legioner

этот код сидит в апплете, не шути так больше.

wfrr ★★☆
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.