C语言 在这个无锁堆栈的pop函数中,free()是安全的吗?

92dk7w1h  于 2023-05-06  发布在  其他
关注(0)|答案(1)|浏览(168)

我一直在研究无锁堆栈。
我正在阅读这个link和弹出功能让我想知道。
根据该链接,弹出功能实现如下。

int lfstack_pop(_Atomic lfstack_t *lfstack)
{
    lfstack_t next, orig = atomic_load(lfstack);

    do{
       if(orig.head == NULL)
       {
            return -1;
       }
       next.head = orig.head->next;
       next.tag = orig.tag+1; //increase the "tag"
    }while(!atomic_compare_exchange_weak(lfstack,&orig,next));

    printf("poping value %d\n",orig.head->data);
    free(orig.head);

    return 0;
}

在上面的实现中,我们通过使用单独的标签信息来解决阿坝问题。
到目前为止,一切顺利。
但我的问题是。
next.head = orig.head->next;行是线程安全的吗?
如果next.head = orig.head->next;行在线程1中的free(orig.head);之后在线程2中恢复,这不是一个错误,因为我们在orig.head被释放之后引用next
我看到的链接没有提到这个问题,所以我想知道这是否安全。

jtjikinw

jtjikinw1#

next.head = orig.head->next;行是线程安全的吗?
如果next.head = orig.head->next;行在线程1中的free(orig.head);之后在线程2中恢复,这不是一个错误,因为我们在orig.head被释放之后引用next?
你已经在函数中发现了一个真正的缺陷。干得好
两个线程并发执行lfstack_pop()确实可以将相同的值加载到各自的orig局部变量中。尽管每个线程的orig都是该线程的本地指针,但两个orig.head指针都指向同一个对象。在这种情况下,如果一个线程在另一个线程执行orig.head-〉next之前执行free()操作它的orig.head,那么第二个线程将由于取消引用不确定的指针值而获得未定义的行为。没有什么特别的东西阻止它。 请注意,就C语言规范而言,即使在过渡期间,在orig.head`最初指向的地址处分配了新节点,该行为仍然是未定义的。(这就是阿坝问题出现的情况,代码声称要解决这个问题。

相关问题