【发布时间】:2011-08-30 20:09:04
【问题描述】:
如何在C 中实现这个无锁队列伪代码?
ENQUEUE(x)
q ← new record
q^.value ← x
q^.next ← NULL
repeat
p ← tail
succ ← COMPARE&SWAP(p^.next, NULL, q)
if succ ≠ TRUE
COMPARE&SWAP(tail, p, p^.next)
until succ = TRUE
COMPARE&SWAP(tail,p,q)
end
DEQUEUE()
repeat
p ← head
if p^.next = NULL
error queue empty
until COMPARE&SWAP(head, p, p^.next)
return p^.next^.value
end
如何使用Built-in functions for atomic memory access
__sync_bool_compare_and_swap (type *ptr, type oldval type newval, ...)
我现在有
typedef struct queueelem {
queuedata_t data;
struct queueelem *next;
} queueelem_t;
typedef struct queue {
int capacity;
int size;
queueelem_t *head;
queueelem_t *tail;
} queue_t;
queue_t *
queue_init(int capacity)
{
queue_t *q = (queue_t *) malloc(sizeof(queue_t));
q->head = q->tail = NULL;
q->size = 0;
q->capacity = capacity;
return q;
}
【问题讨论】:
-
使用全局变量的唯一“方便”是它可以让你变得懒惰并避免一些打字。既然你正在做并发编程,你应该为你甚至问过这个问题而感到羞耻。 :-)
-
这与您提出的最后一个问题有何不同(例如,不是重复)?
-
请注意,以
_t结尾的名称在某些标准(POSIX,不确定实际标准)中保留,不应在您的代码中使用。您应该使用不同的命名约定。 -
Lock-free queue的可能重复
-
一些生活规则。 1) 始终从列表的 HEAD 中添加/删除。快点!更简单!单个 CAS 将从列表中添加/删除项目,并且您消除了大量的竞争条件。如果你必须做不止一个 CAS,你将不得不处理比赛条件。使用单个 CAS 无法更改尾部项目的下一个 ptr,然后同时更改头部或尾部。改变列表的头指针是! 2) 仅当您移除物品并将其放回时才担心 ABA。如果您只将新的 ptrs 添加到列表中,您将不会拥有 ABA。