现象: gdb bt 卡在 spinlock_unlock() 位置。

  1. 查了半天代码,我的每一个锁都没有问题。给我看吐血了。

  2. 最后没辙了灵机一动 gdb disassemble 发现这里死循环了:

gdb disassemble

原来是一个标志位没有设置为 volatile ,代码被优化了。大概的代码如下:

while (true) {
    // 多线程中可以被修改的一个标志
    if (flags_1 == STATUS_1) { 
        continue
    }
    // 其他逻辑
    // ... ...
}

但是为什么不是必现的 BUG 呢? AI 给了一堆解释,但是没怎么看懂。

举报· 1347 次点击
登录 注册 站外分享
12 条回复  
anytk 小成 3 天前
跨线程的话,一般推荐用原子变量来做标志,内存序可以用 relaxed. volatile 基本留给硬件寄存器读写和 sig_atomic_t 了.
echoechoin 楼主 小成 3 天前
@anytk 想来也是不应该写这种死循环,AI 建议使用 refcnt 可以多个线程在 STATUS_1 状态下继续后续的代码,但是我也懒得改了。。。
aviator 初学 3 天前
volatile 提供了多线程访问的可见性,是得加
qzhai 小成 3 天前
分享一个死循环给我?我写死循环的经验可是多得很
PTLin 小成 3 天前
简单来说就是你没用任何同步手段,例如原子变量,内存屏障,volatile 。你这种情况下有可能会遇到 指令重排,例如把你这个判断的代码重排到后面。 从缓存中读取,例如把你这个 flags 放到寄存器里,然后从寄存器里读出。 操作拆分,例如把你这个读取操作在汇编的实现中拆分成两次内存操作。 相关的东西你还是去了解下内存序什么的吧。
wfg 初学 3 天前
你贴的代码,不管有没有 continue 不都是继续循环吗?
ccpp132 小成 3 天前
c++的话 volatile 也不算对,应该用 atomic ,这点和 java 还不是一回事
PTLin 小成 3 天前
@PTLin 甚至在一些情况下,编译器发现你后续代码没用操作这个变量,虽然你这个变量的操作是在其他线程,但是编译器并不知道这些信息,因为你没用同步手段,编译器可能会激进的吧你这个判断删除。
yyysuo 初学 3 天前
@qzhai 大家都不怎么服气的。
12下一页
返回顶部