Вы можете попробовать использовать обновляемую блокировку чтения / записи (может быть, она называется обновляемой общей блокировкой и т. Д., Я не знаю, что обеспечивает Java): используйте один RWLock для всего дерева. Перед обходом B-дерева вы получаете блокировку чтения (совместно используемую) и освобождаете ее, когда закончите (одно получение и одно освобождение в методе add, не более).
В тот момент, когда вам нужно изменить B-дерево, вы получаете блокировку записи (эксклюзивную) (или "обновление" с блокировки чтения на запись), вставляете узел и понижаете рейтинг до чтения ( общая) блокировка.
С помощью этой техники также можно удалить синхронизацию для проверки и вставки головного узла!
Это должно выглядеть примерно так:
public void add(String sortedWord, String word) {
lock.read();
if (head == null) {
lock.upgrade();
head = new TreeNode(sortedWord, word);
lock.downgrade();
lock.unlock();
return;
}
TreeNode current = head, previous = null;
while (current != null) {
if (current.getSortedWord().equals(sortedWord)) {
lock.upgrade();
current.add(word);
lock.downgrade();
lock.unlock();
return;
}
.. more tree traversal, do not touch the lock here ..
...
}
if (previous.compareTo(sortedWord) > 0) {
lock.upgrade();
previous.setLeft(sortedWord, word);
lock.downgrade();
}
else {
lock.upgrade();
previous.setRight(sortedWord, word);
lock.downgrade();
}
lock.unlock();
}
К сожалению, после некоторого поиска в Google я не смог найти подходящий "рутируемый" рулок для Java. «Класс ReentrantReadWriteLock» не может быть обновлен, однако вместо обновления вы можете разблокировать чтение, затем заблокировать запись и (очень важно): повторно проверить условие, которое приводит к этим строкам , снова (например, if( current.getSortedWord().equals(sortedWord) ) {...}
). Это важно, потому что другой поток мог изменить вещи между разблокировкой чтения и блокировкой записи.
для подробной информации проверьте этот вопрос и его ответы
В конце обход B-дерева будет проходить параллельно. Только когда целевой узел найден, поток получает эксклюзивную блокировку (а другие потоки будут блокироваться только на время вставки).