Ответ 1
Да, добавление - простой двухступенчатый цикл с CAS в предыдущем указателе .Next; но удаление трудно!
На самом деле вы не можете сделать это, не используя дополнительную информацию и логику.
Харрис создал решение этой проблемы, добавив бит маркера, который когда-то запретил кому-либо изменять node. Удаление становится двухступенчатым: сначала (CAS) отметьте удаленный node, чтобы никто не мог его изменить (особенно указатель .Next); второй CAS - предыдущий указатель node.Next, который теперь безопасен, поскольку отмечен другой node.
Проблема в том, что в C Harris использовались два наименее значимых бита указателя .Next как маркер. Это умно, потому что с 4-байтовыми ориентированными указателями они всегда не используются (т.е. 00), и поскольку они подходят к 32-битовому указателю, они могут быть CAS атомарно с самим указателем, что является ключом к этому алгоритму. Конечно, это невозможно в С#, по крайней мере, без использования небезопасного кода.
Решение становится немного более сложным и включает дополнительную ссылку на неизменяемый класс, содержащий два поля (.Next + marker).
Вместо того, чтобы вдаваться в подробное объяснение этих идей, я нашел несколько ссылок в Интернете, которые расскажут обо всех деталях, которые вам нужны, см.:
Связанный список без блокировки (часть 1) Объясняет проблему:
Link-Free Linked List (часть 2) Объясняет решение C + решение для спин-блокировки;
Связанный список без блокировки (часть 3) Объясняет ссылку на неизменяемое состояние;
Если вы действительно интересуетесь этой темой, есть научные статьи с различными решениями и анализ их эффективности, например. этот: Не привязанные по ссылке списки и списки пропуска