При написании многопоточной реализации BST в Java я пришел к следующей проблеме. Этот BST не должен использовать глобальную блокировку, а должен блокировать как можно меньше, в частности, только те узлы, которые меняются (команда добавления и удаления). Таким образом, другие потоки могут быть активны в дереве, если они не пытаются изменить те же узлы, что и вы.
Я не могу найти способ реализовать удаление узла, который имеет 2 дочерних элементов. Обычный алгоритм говорит, что нужно найти преемника по порядку удаляемого узла, поместить его вместо удаленного узла, а затем удалить скопированный узел. Но это может создать проблему для потока, который находится между этими двумя узлами и нуждается в скопированном узле, после передачи поток не найдет запрошенный узел, даже если он находится в дереве.
Посмотрите на следующий пример: шаг 1 выполняет remove(5)
. Он находит и копирует следующий ключ (6) в узел, а затем удаляет узел из копии. Но в то же время другой поток, выполняющий команду contains(6)
и ожидающий на узле 8, после того, как исполняющий узел номер 6 больше не будет находиться на своем пути, и он вернет ложный результат, даже если узел 6 все еще находится в дереве .
Иллюстрация состояния перед командой удаления (синяя стрелка указывает, где находится поток 2 nd .
Иллюстрация состояния после команды удаления (синяя стрелка указывает, где находится поток 2 nd .
Как я могу преодолеть эту проблему, не блокируя все дерево?