У меня есть следующее определение проблемы:Блокировка свободный список удалить операцию
Дизайн замок свободной простой связанный список со следующими операциями:
- Добавить (пункт): добавить узел в начало (руководитель) списка
- Remove (пункт): удалить данный пункт из списка
Ниже показан код реализован до сих пор:
public class List<T>
{
private readonly T _sentinel;
private readonly Node<T> _head;
public List()
{
_head = new Node<T>();
_sentinel = default(T);
}
public List(T item)
{
_head = new Node<T>(item);
_sentinel = item;
}
public void Add(T item)
{
Node<T> node = new Node<T>(item);
do
{
node.Next = _head.Next;
}
while (!Atomic.CAS(ref _head.Next, node.Next, node));
}
public void Remove(Node<T> item)
{
Node<T> next;
Node<T> oldItem = item;
if (item.Value.Equals(_sentinel))
return;
item.Value = _sentinel;
do
{
next = item.Next;
if (next == null)
{
Atomic.CAS(ref item.Next, null, null);
return;
}
} while (!Atomic.CAS(ref item.Next, next, next.Next));
item.Value = next.Value;
}
}
Голова на самом деле является фиктивным (дозорным) узлом, предназначенным для удобства использования. Практический руководитель на самом деле _head.Next. Проблема заключается в операции удаления при попытке удалить последний элемент из списка:
На REMOVE части есть два случая:
- Узел имеет следующие not- null следующий указатель: затем выполните операцию CAS и украдите данные о значении следующего элемента, удалив фактически следующий элемент.
- Проблемный случай, когда элемент для удаления является последним в списке:
- Do Atomically: If (item == oldItem и item.Next == null) then item = null где oldItem - указатель на удаляемый элемент;
Так что я хочу сделать, это в случае удаления C узла:
- если (C == старого C-ссылки и C .next = = null), то C = null => all atomically
Проблема в том, что у меня есть CAS только на одном объекте. Как я могу решить эту проблему атомарно? Или есть лучший способ сделать эту операцию удаления, которую я упускаю здесь?
Вы уверены, что вещь _sentinel работает? С типами значений невозможно отличить значение по умолчанию (T) и потенциально полезное значение. Другими словами, система типа .NET не предоставляет вам значение, которое можно использовать как часовое. – usr
Действительно, значение часового может не работать для типов значений, но для простоты использования давайте просто определим предопределенный маркер как дозорный. Если вы знаете лучшее решение, пожалуйста, разделите его (https://gist.github.com/). Однако моя основная проблема заключается в операции удаления. –
Ваше удаление не имеет для меня никакого смысла. Если вы хотите удалить B, вам нужно CAS A.next to C. Справа? Ваш код этого не делает. Я признаю, что это первый раз, когда я работаю над атомарным списком. – usr