【问题标题】:Lock free list with sync_val_compare_and_swap使用 __sync_val_compare_and_swap 锁定空闲列表
【发布时间】:2012-07-13 16:33:09
【问题描述】:

我正在尝试提供一种线程安全的方式来更新对象。我看过一些关于它的帖子,但没有一个能 100% 回答我的问题。

我想要做的是维护一个名为“m_First”的指针来指向我的数据。如果有人调用 get,我会尊重该指针,返回对它指向的对象的引用。

如果有人调用 set,传入一个指向新对象的指针,我们将该指针添加到我们的列表中并更新 m_First 以指向新对象。

我将对象存储在一个向量中,以便我们完成后可以清理内存。

目前我已经定义了这些成员:

std::vector<MyObject*> m_List;
const MyObject* m_First;

First 是这样初始化的。 m_First = m_List.back();

我想让多个线程读取 m_First,同时多个线程也写入 m_First。

我的班级有两个方法

MyObject& getMyObject() {return *m_First;}

void setMyObject(MyObject* newObj) {

  m_List.push_back(newObj); // add to list so we can later cleanup mem

  do {
    Node* oldHead = m_First;
  } while (!__sync_bool_compare_and_swap(m_First, *oldHead, *newObj));
}

我想知道的是,在 get 方法线程安全中返回 *m_First。即我可以安全地取消引用它并返回对对象的引用,而另一个线程正在尝试更新 m_First,还是我需要使用某种原子方法来读取 m_First。

任何建议/帮助将不胜感激。

【问题讨论】:

  • 但是...这看起来像是一个只推送的空闲列表,不是吗?当 get 只返回当前 head 元素的点而不从列表中弹出它时,你如何获取已推送到列表中的对象?

标签: c++ lock-free compare-and-swap


【解决方案1】:

为了确保从内存而不是寄存器中读取值,您需要进行原子读取。

有不同的方法来实现这一点。在某些系统上,通过像*(const volatile MyObject*)p 这样的易失性指针转换读取对齐的字长值将起作用。但由于您已经在使用内置原子操作,您可以使用 __sync_add_and_fetch 之类的东西加上 0。

【讨论】:

  • 据我所知,__sync_add_and_fetch 仅适用于整数类型。易失性指针强制转换可能有效。我试试看,
【解决方案2】:

我想让多个线程读取 m_First,同时多个线程也写入 m_First。

多个线程如何写入m_First?如果是通过setMyObject,那么他们都会同时修改m_List 向量,这将是一场数据竞争,并且几乎肯定会破坏向量。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-09
    • 1970-01-01
    • 2011-11-21
    • 1970-01-01
    相关资源
    最近更新 更多