Я предполагаю, что первый фрагмент должен представлять собой детализированную версию, а другой - грубую версию.
В "мелкозернистой" версии отсутствует блокировка для создания root узел. Кроме того, вы удерживаете блокировку для назначения нового узла, вы не делаете этого для условия. Пока вы выполняете итерацию дерева, блокировка узла за раз недостаточна при наличии одновременных удалений. Все это проблемы параллелизма.
Обычно разница между мелкозернистой и крупнозернистой блокировкой - это не «размер» ваших секций блокировки (количество кода, которое вы закрываете блокировкой), это относится к детализации блокировки по отношению к самой структуре данных.
Итак, один из подходов заключается в том, чтобы иметь единую блокировку для всего дерева - грубую блокировку. Другой подход заключается во введении блокировок на более низких уровнях (например, для каждого узла), чтобы устранить конфликт блокировок, если две параллельные операции выполняются на разных узлах дерева. Это похоже на разницу между блокировками таблиц и блокировками на уровне строк в пространстве базы данных.
Один из подходов для детальной версии состоит в том, чтобы иметь блокировку для каждого узла и использовать так называемую ручную передачу ручная блокировка. Для операции вставки вам нужно будет заблокировать текущий узел, пока вы не определите и не заблокируете следующий узел при спуске.
Проведите дополнительное исследование, измените свою реализацию соответствующим образом и повторите тест.
Обычно говоря точнее, мелкозернистая блокировка может привести к более масштабируемой реализации, если шаблон доступа имеет тенденцию поражать различные блокировки. Если это не так в большинстве случаев, то крупнозернистая версия может работать так же хорошо или немного лучше, потому что единственная блокировка может удерживаться на протяжении всей операции, а не требовать получения разных блокировок, при этом большинство из них снова приводит к конфликту блокировок. Как всегда, это зависит от фактического шаблона использования.