标准实现无锁化队列的例子

标准实现无锁化队列的例子

以下 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;
}

参考链接: 无锁化队列

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值