gpt4 book ai didi

c++ - 如何使用 C++11 原子库实现 seqlock 锁

转载 作者:太空狗 更新时间:2023-10-29 21:44:20 39 4
gpt4 key购买 nike

我想使用 C++11 原子库编写一个 seqlock。我在 stackoverflow 上看了一些关于 seqlock 的问题,但是没有人帮助我。我用的算法很普通,到处都能找到。这就是我的代码:

struct sequence_spinlock_t {

void write_lock() {
lock.lock();
flags.fetch_add(1, memory_order_acquire); //A

}

void write_unlock() {
flags.fetch_add(1, memory_order_release); //B
lock.unlock();
}

void read_enter(uintptr_t *flag) {
for (;;) {
uintptr_t f = flags.load(memory_order_acquire); //C
if ((f & 1) == 0) {
*flag = f;
break;
}
pause();
}
}

bool_ read_leave(uintptr_t flag) {

uintptr_t f = flags.load(memory_order_relaxed); //D
return f == flag;
}

spinlock_t lock;
atomic_uintptr_t flags;
};

//read thread
uintptr_t flag;
do {
lock.read_enter(&flag); (0)
//read something (1)
} while(!lock.read_leave(flag)) (2)


//write thread
lock.write_lock(); (3)
//write something (4)
lock.write_unlock(); (5)

我确保在 B 和 C 处正确使用 memory_order 标签。

我不认为 A 和 D 是正确的。

想想我们同时读写 protected 数据,我担心D处的flags读取值太旧,我们没有读取write_lock()写入的最新值。但是我们读取了最新值写入线程写入的 protected 数据(这可能不会发生在 x86 系统上,但我不假设代码在 x86 上运行。)。读取线程完成读取 protected 数据后,因为标志的读取值太旧,我没有发现序列已增加。读取线程从循环中退出,我们制造了一个错误。

(1)处的protected data读取值写入(4)处,(2)处的flags读取值未写入(3)处(上次解锁写锁时写入。) .这就是我认为存在错误的原因。

但我真的不知道如何解决这个问题。我试图在 read_leavee() 和 write_locke() 之间建立“同步”关系(我希望“read_leave() 与 write_locke() 同步”)。但是有read_leave()中没有store action,所以失败了。

(哦!c++标准规范对我来说太难理解了。部分原因是我不是来自英语国家。)

最佳答案

在 read_leave 中使用 memory_order_relaxed 本身是可以的,但是您确实需要确保在加载标志变量之前已经加载了数据值。你可以用 std::atomic_thread_fence 做到这一点。 IE。你的 read_leave 应该看起来像

 
  
bool read_leave(uintptr_t flag) { atomic_thread_fence(memory_order_acquire); uintptr_t f = flag.load(memory_order_relaxed); return f == flag;}

FWIW,通过此更改,您的代码看起来与 http://safari.ece.cmu.edu/MSPC2012/slides_posters/boehm-slides.pdf 中的示例 3 大致相同。

关于c++ - 如何使用 C++11 原子库实现 seqlock 锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20342691/

39 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com