无锁队列学习

深入原理 - 使用CAS实现无锁队列

深入理解一致性与 C++ 内存模型

Simple, Fast, and Practical Non-Blocking and Blocking Concurrent Queue Algorithms

文章目录

CAS

bool compare_and_swap(int *addr, int oldval, int newval)
{
  if( *addr != oldval ){
      return false;
  }
  *addr = newval;
  return true;
}

C++ CAS

template<class T >
boolatomic_compare_exchange_weak( std::atomic* obj,
                                   T* expected, T desired );
template<class T >
boolatomic_compare_exchange_weak(volatile std::atomic* obj,
                                   T* expected, T desired );

EnQueue

在这里插入图片描述

EnQueue(Q, data) //进队列
{
    //准备新加入的结点数据
    n = newnode();
    n->value = data;
    n->next = NULL;

    do{
        p = Q->tail; //取链表尾指针的快照
    }while(CAS(p->next, NULL, n) != TRUE); 
    //while条件注释:如果没有把结点链在尾指针上,再试

    CAS(Q->tail, p, n); //置尾结点 tail = n;
}
EnQueue(Q, data) //进队列改良版 v1
{
    n = newnode();
    n->value = data;
    n->next = NULL;

    p = Q->tail;
    oldp = p
    do{
        while(p->next != NULL)
            p = p->next;
    }while(CAS(p.next, NULL, n) != TRUE); //如果没有把结点链在尾上,再试

    CAS(Q->tail, oldp, n); //置尾结点
}
EnQueue(Q, data) //进队列改良版 v2 
{
    n = newnode();
    n->value = data;
    n->next = NULL;

    while(TRUE){
        //先取一下尾指针和尾指针的next
        tail = Q->tail;
        next = tail->next;

        //如果尾指针已经被移动了,则重新开始
        if( tail != Q->tail )continue;

        //如果尾指针的 next 不为NULL,则 fetch 全局尾指针到next
        if( next != NULL){
            CAS(Q->tail, tail, next);
            continue;
        }

        //如果加入结点成功,则退出
        if(CAS(tail->next, next, n) == TRUE)break;
    }
    CAS(Q->tail, tail, n); //置尾结点
}

final

// https://mp.weixin.qq.com/s/0s3lDd4YdgqKUb-pQxYb2Q
// https://www.cs.rochester.edu/research/synchronization/pseudocode/queues.html#nbq

InitQueue(Q)
{
    node = newnode();
    node->next = NULL;
    Q->head = Q->tail = node; //初始化一个dummy结点
}

EnQueue(Q, data) //进队列改良版 v2
{
    n = newnode();
    n->value = data;
    n->next = NULL;

    while (TRUE)
    {
        //先取一下尾指针和尾指针的next
        tail = Q->tail;
        next = tail->next;

        //如果尾指针已经被移动了,则重新开始
        if (tail != Q->tail)
            continue;

        //如果尾指针的 next 不为NULL,则 fetch 全局尾指针到next
        if (next != NULL)
        {
            CAS(Q->tail, tail, next);
            continue;
        }

        //如果加入结点成功,则退出
        if (CAS(tail->next, next, n) == TRUE)
            break;
    }
    CAS(Q->tail, tail, n); //置尾结点
}

DeQueue(Q) //出队列,改进版
{
    while (TRUE)
    {
        //取出头指针,尾指针,和第一个元素的指针
        head = Q->head;
        tail = Q->tail;
        next = head->next;

        // Q->head 指针已移动,重新取 head指针
        if (head != Q->head)
            continue;

        if (head == tail)
        {
            if (next == NULL)
                return ERR_EMPTY_QUEUE; // 如果是空队列
            //如果 tail 指针落后了
            CAS(Q->tail, tail, next);
            continue;
        }

        //移动 head 指针成功后,取出数据
        if (CAS(Q->head, head, next) == TRUE)
        {
            value = next->value;
            break;
        }
    }
    free(head); //释放老的dummy结点
    return value;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值