【问题标题】:A lock-free data structure that doesn't have race condition没有竞争条件的无锁数据结构
【发布时间】:2022-01-15 21:07:33
【问题描述】:

在我的操作系统课程中,我们有一个关于如何修改无锁堆栈代码使其免受竞争条件的练习,但我不明白无锁数据结构如何具有竞争条件以及如何CAS在这里工作。问题是:

compare 和 swap() 指令可用于设计无锁 数据结构,例如堆栈、队列和列表。程序示例 下面显示了无锁堆栈的可能解决方案 使用 CAS 指令,其中堆栈表示为链表 节点元素的顶部表示堆栈的顶部。这个实现没有竞争条件吗?(我无法解决)

typedef struct node {
    value t data;
    struct node* next;
} Node;

Node* top; // top of stack
void push(value t item)
{
    Node* old node;
    Node* new node;
    new node = malloc(sizeof(Node));
    new node->data = item;
    do {
        old node = top;
        new node->next = old node;
    } while (compare and swap(top, old node, new node) != old node);
}

value t pop()
{
    Node* old node;
    Node* new node;
    do {
        old node = top;
        if (old node == NULL)
            return NULL;
        new node = old node->next;
    } while (compare and swap(top, old node, new node) != old node);
    return old node->data;
}

【问题讨论】:

  • Node* old node; 不是有效的 C++。 new node = malloc(sizeof(Node)); 不是有效的 C++。 compare and swap(top, old node, new node) 也不是有效的 C++。看起来所示代码中大约有一半的行无法编译。如果您的问题与 C++ 相关,您能否展示真实的 C++ 代码,并针对显示的代码解释您的问题是什么?
  • 我的主要问题是“这个实现是否没有竞争条件?” @SamVarshavchik
  • 是的,竞争条件只影响可以运行的代码。这不会编译(见上面的评论),所以从这个意义上说,它在竞争条件下是微不足道的。
  • 谢谢,我忘了。 @dratenik
  • 哦,有趣!谢谢你。@dratenik

标签: operating-system


【解决方案1】:

我认为您需要展示一场比赛的样子。让我们用一个简单的赋值替换 compare_and_swap:

void push(value_t item)
{
    Node* old_node;
    Node* new_node;
    new_node = malloc(sizeof(Node));
    new_node->data = item;
        old_node = top;
        new_node->next = old_node;
    top = new_node;
}

这将在单线程中做同样的事情,但在多线程中应该容易出现竞争。

现在让我们同时运行其中两个(通过添加所有内容的第二个副本来模拟)。会出什么问题?

void push(value_t item, value_t item2)
{
    Node* old_node;
    Node* old_node2;
    Node* new_node;
    Node* new_node2;
    new_node = malloc(sizeof(Node));
    new_node2 = malloc(sizeof(Node));
    new_node->data = item;
    new_node2->data = item2;
        old_node = top;
        old_node2 = top;
        new_node->next = old_node;
        new_node2->next = old_node2;
    top = new_node;
    top = new_node2;
}

top = new_node 的结果会立即被top = new_node2 覆盖,所以最后我们只插入了item2item 的值丢失了。

这里的核心问题是访问共享内存,即top 变量。两个线程都读取了它,线程 1 更新了它,线程 2 继续使用现在过期的值并基于它进行了自己的更新。

这就是 compare_and_swap 循环要防止的。

【讨论】:

  • 所以 CAS 函数将“顶值”从“旧节点”转移到“新节点”而不丢失某些节点的值,因此这段代码没有竞争条件。
猜你喜欢
  • 2012-01-10
  • 2014-11-08
  • 1970-01-01
  • 2012-04-08
  • 1970-01-01
  • 2012-04-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多