Я могу вспомнить пару общих подходов, которые не включают глобальную блокировку и должны позволить некоторую степень продвижения вперед:
1. пометить, но не удалять
Когда поток удаления идентифицирует свою жертву, пометьте ее как удаленную, но оставьте ее на месте.
Когда поисковый поток встречает узел с этой удаленной меткой, он просто игнорирует его.
Вам нужно будет создать барьер записи / освобождения после пометки удаленного узла и барьер получения перед проверкой значения: вам понадобятся специфичные для платформы, специфичные для компилятора расширения, в противном случае вы пишете эти барьеры в ассемблер.
2. подлинное удаление со списком без блокировки
Согласно статье в ответе Пеееша; аналогичные требования к платформе или компилятору для CAS, и требуется значительная осторожность. Такие опции, как refcounts или указатели опасности, могут позволить подлинному удалению узла, когда никто не смотрит на него. Вы можете обнаружить, что вам нужно заменить ваши предыдущие / следующие указатели на short
индексы, которые вы можете упаковать в одно слово для работы CAS: это означает ограничение числа узлов и их размещение в массиве.
Также обратите внимание, что хотя каждый поток должен иметь возможность продвигаться по схеме такого рода, отдельные операции (например, переход к следующему узлу) могут стать намного более дорогостоящими из-за требований синхронизации.