lock-free ABA问题重现

在多线程编程中,同步时会发生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;
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 一、Python简介和环境搭建以及pip的安装 4课时实验课主要内容 【Python简介】: Python 是一个...
    _小老虎_阅读 11,120评论 0 10
  • 一、课程导学 二、基本概念 并发:同时拥有两个或者多个线程,如果程序在单核处理器上运行,多个线程将交替地换入或者换...
    匆匆岁月阅读 2,900评论 0 3
  • 本文主要讲了java中多线程的使用方法、线程同步、线程数据传递、线程状态及相应的一些线程函数用法、概述等。 首先讲...
    李欣阳阅读 7,186评论 1 15
  • 在C语言中,五种基本数据类型存储空间长度的排列顺序是: A)char B)char=int<=float C)ch...
    夏天再来阅读 8,707评论 0 2
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 13,794评论 1 32