Это является поточно-ориентированным, если предположить, что область вашей блокировки (то есть что она блокирует, ничего общего с официальным термином "область действия", используемым в C) достаточно велика.
Если он блокирует только текущий узел p
, то вы не можете полагаться на другие потоки, не входящие и не играющие с prev
(или head
или tail
в этом отношении) и, следовательно, занижающие вы.
Если она блокирует всю структуру, то да, она поточно-ориентирована.
Мы не можем определить объем вашей блокировки по приведенному коду, но я упомяну еще одну (не связанную) вещь.
Возможно, вам следует либо бесплатно p
, либо добавить его в список бесплатных для повторного использования. Просто установив указатель next
на ноль, а его флаг deleted
на 1, вы не сможете найти его, когда вам потребуется его повторно использовать. Это приведет к утечке памяти. Может быть, код для этого просто не показан, но я решил упомянуть об этом, на всякий случай.
На основании ваших правок, где вы заявляете, что вы используете детальный подход (одна блокировка на узел):
При условии, что вы заблокируете все три «узла», которые вы используете или изменяете, и что вы блокируете их в согласованном направлении, это все еще поточно-ориентировано.
Я помещаю "узлы" в кавычки, поскольку это также относится к указателям head
и tail
. Например, если вы хотите удалить первый узел в списке из десяти узлов, вам нужно заблокировать переменную head
, а также первый и второй узлы в указанном порядке. Чтобы удалить последний узел в списке с одним узлом, необходимо заблокировать как переменные head
и tail
, так и узел.
Блокировка всех трех «узлов» предотвратит отрицательное влияние потоков друг на друга.
Блокировка их в последовательном направлении (например, от head
к tail
) предотвратит взаимоблокировку.
Но вы должны заблокировать все три, прежде чем пытаться что-либо изменить.
Это даже предотвратит одновременные операции вставки, если вставка блокирует два «узла» по обе стороны от точки вставки и, конечно, блокирует их в одном направлении.
Не уверен, насколько хороши итерации по списку. Вероятно, вы могли бы обойтись без системы, в которой вы сначала заблокируете переменную head
и первый узел, а затем отпустите head
.
Затем, когда вы закончили работу с этим узлом, заблокируйте следующий, прежде чем освободить текущий. Таким образом, вы сможете выполнять итерацию по списку, не подвергаясь воздействию вставок или удалений, что может происходить только в тех областях, с которыми вы в данный момент не работаете.
Но суть в том, что вы, безусловно, можете сделать его безопасным для потоков, даже с мелкозернистым замком.