美文网首页
lock-free ABA问题重现

lock-free ABA问题重现

作者: Teech | 来源:发表于2019-07-29 17:19 被阅读0次

在多线程编程中,同步时会发生ABA问题。上述代码就是重现ABA问题,当一个地址需要被read2次,这个值没有改变意味着没有人修改这个值。然而其他线程执行可能会修改这个值在两次read之间,只是又把这个值修改回去了。

  • 线程P1读取值A从共享内存中
  • P1运行后,P2在运行。
  • P2 修改存储A的共享内存修改为B,然后在修改回A
  • P1继续执行,发现存储A的共享内存处的值并没有变化,于是继续运行
    这个可能会造成一些隐藏的问题在修改这块共享内存之后。
    最经常会出现ABA问题的一个情况,就是编写lock-free程序时,包含指针的情况。如果一个item从列表中移出以及释放掉,接着一个新的item被分配以及加入列表。新分配的item和之前释放掉的item指针相同这个经常会发生的(基于内存分配器的分配策略)。这个就导致了ABA问题了。
    简书中链接跳转到github一直提示不安全的链接,所以把链接贴进来。https://github.com/iamjokerjun/abaTest
    这个是个ABA问题的栈操作。列举下步骤
  1. 初始化栈 top->A->B->C
    Push(&C);
    Push(&B);
    Push(&A);
  1. thread1的worker1先运行,thread2阻塞到等待信号量。thread1中的局部变量retPtr指向A,nextPtr指向B,接着post信号量,然后sleep 2秒,有足够的时间让thread2 执行完代码
    for(;;){
        struct Obj* retPtr = topPtr;
        if(!retPtr)
            return NULL;
        struct Obj* nextPtr  = retPtr->next;
        //第一步 retPtr指向A nextPtr指向B
        if(bSleep)
        {
            sem_post(&Sema); //post信号量
            sleep(2);
            fprintf(stdout,"i am wake up topPtr.value[%c] retPtr.value[%c] nextPtr.value[%c]\n",((struct Obj*)topPtr)->value,retPtr->value,nextPtr->value);
        }
        if(topPtr.compare_exchange_weak(retPtr,nextPtr))
            return retPtr;
    }
  1. thread2的worker2开始运行了,最后结果为top->A->C.注意这里A我们是全局的变量,不会被释放的。这里就等于模拟了,释放了A后,在分配一块内存,内存地址和A是一样的。
    Pop(false); //top -> B -> C
    Pop(false); //top -> C
    Push(&A);   //top ->A -> C
  1. thread1的worker1开始苏醒过来了。执行这段代码,判断topPtr和retPtr地址都相同,所以就用nextPtr替换topPtr,注意到步骤1中,nextPtr指向B的,要知道B在步骤3中第一个Pop中已经被释放了。
        if(topPtr.compare_exchange_weak(retPtr,nextPtr))
            return retPtr;

运行的结果如下

Obj A malloc
Obj B malloc
Obj C malloc
worker1 is work
worker2 is wake
worker2 is over
i am wake up topPtr.value[A] retPtr.value[A] nextPtr.value[B]
worker1 is over
Obj C free
Obj B free
Segmentation fault

为了保证每次必定crash,我在调用之后把栈上数据清0,所以一定会崩溃。

    testFun();
    char array[64] = {0,};      //栈上之前分配的B,C虽然已经释放掉了,但是栈上数据还存在。所以把栈数据清0,让其必定崩溃。
    struct Obj* APtr = topPtr;

相关文章

  • lock-free ABA问题重现

    在多线程编程中,同步时会发生ABA问题。上述代码就是重现ABA问题,当一个地址需要被read2次,这个值没有改变意...

  • 死磕 java并发包之AtomicStampedReferenc

    问题 (1)什么是ABA? (2)ABA的危害? (3)ABA的解决方法? (4)AtomicStampedRef...

  • 原子操作 CAS CompareAndSwap

    参考 Java CAS ABA问题发生的场景分析 提到了ABA问题 Unsafe$compareAndSwapIn...

  • ABA问题

    CAS会导致“ABA问题”。 线程1准备用CAS将变量的值由A替换为C,在此之前,线程2将变量的值由A替换为B,又...

  • 细谈CAS与ABA

    题目:如何实现乐观锁(CAS),如何避免ABA问题? 这个题主要考查原子操作、悲观锁、乐观锁及ABA问题。 原子操...

  • CAS ABA问题

    java.util.concurrent包的最底层基础CAS技术,原理很简单。 CAS有3个操作数,内存值V,旧的...

  • 并发和Read-copy update(RCU)

    简介 在上一篇文章中的并发和ABA问题的介绍中,我们提到了要解决ABA中的memory reclamation问题...

  • Java多线程22 Atomic

    ABA问题 输出true 解决 添加版本号

  • JUC之ABA问题

    什么是ABA问题? ABA问题是由CAS而导致的一个问题 CAS算法实现一个重要前提需要取出内存中某时刻的数据并在...

  • CAS中的ABA问题

    补档CAS中的ABA问题。 要特别注意,常见的ABA问题有两种,要求能分别举例解释。 CAS的使用可参考:源码|并...

网友评论

      本文标题:lock-free ABA问题重现

      本文链接:https://www.haomeiwen.com/subject/bitirctx.html