标准实现无锁化队列的例子
以下 V2 版本是 标准版本,CAS 操作根据自身语言特性来实现
struct node {
node *next;
int value;
};
struct queue {
node *head;
node *tail;
};
void InitQueue(queue *Q) {
node *no = new node();
no->next = nullptr;
Q->head = Q->tail = no;
}
// 有问题
void EnQueue(queue *Q, int data) //进队列
{
//准备新加入的结点数据
node *n = new node();
n->value = data;
n->next = nullptr;
node *p = nullptr;
do {
p = Q->tail; //取链表尾指针的快照
} while (CAS(p->next, nullptr, n) != true);
// 如果某个线程在这里挂掉会导致其他线程一直阻塞在这里
//while条件注释:如果没有把结点链在尾指针上,再试
CAS(Q->tail, p, n); //置尾结点 tail = n;
}
void EnQueueV2(queue *Q, int data) //进队列改良版 v2
{
node *n = new node();
n->value = data;
n->next = nullptr;
node *tail = nullptr;
while (true) {
//先取一下尾指针和尾指针的next
tail = Q->tail;
node *next = tail->next;
//如果尾指针已经被移动了,则重新开始
if (tail != Q->tail) continue;
//如果尾指针的 next 不为NULL,则 fetch 全局尾指针到next
if (next != nullptr) {
CAS(Q->tail, tail, next);
continue;
}
//如果加入结点成功,则退出
if (CAS(tail->next, next, n) == true)
break;
}
CAS(Q->tail, tail, n); //置尾结点
}
// 有问题
int DeQueue(queue *Q) { //出队列
node *p = nullptr;
do {
p = Q->head;
if (p->next == nullptr) {
return ERR_EMPTY_QUEUE;
}
while (CAS(Q->head, p, p->next) != true);
return p->next->value;
} while (true);
}
int DeQueueV2(queue *Q) //出队列,改进版
{
node *tail = nullptr;
node *head = nullptr;
node *next = nullptr;
int value = 0;
while (true) {
//取出头指针,尾指针,和第一个元素的指针
head = Q->head;
tail = Q->tail;
next = head->next;
// Q->head 指针已移动,重新取 head指针
if (head != Q->head) continue;
// 如果是空队列
if (head == tail && next == nullptr) {
return ERR_EMPTY_QUEUE;
}
//如果 tail 指针落后了
if (head == tail && next != nullptr) {
CAS(Q->tail, tail, next);
continue;
}
//移动 head 指针成功后,取出数据
if (CAS(Q->head, head, next) == true) {
value = next->value;
break;
}
}
delete head; //释放老的dummy结点
return value;
}
参考链接: 无锁化队列