You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于C#中InterLocked.CompareExchange前读取值的疑问

关于C#中InterLocked.CompareExchange与volatile的疑问解答

咱们先拆解你代码里的两个核心疑问:

1. currVal = this.myVal能否读取到myVal的最新值?

在多线程场景下,这行代码不一定能拿到最新值。

原因是现代CPU和编译器会做缓存优化:线程可能会把myVal的值缓存到自己的本地寄存器或CPU缓存中,而非每次都从主内存读取。如果其他线程修改了主内存里的myVal,当前线程可能还在读取缓存里的旧值,导致currVal拿到的不是变量的最新状态。

2. 是否需要为myVal添加volatile修饰符?

必须加。

volatile关键字的作用就是告诉编译器和CPU:这个变量是“易变”的,不能对它做缓存优化——每次读取必须直接从主内存获取,每次写入必须立刻刷新到主内存。这样才能保证currVal = this.myVal这行读取操作,总能拿到其他线程修改后的最新值。

补充说明:InterLocked.CompareExchange的局限性

你提到InterLocked.CompareExchange是原子操作,这点没错,但它只保证自身的原子性(比较+交换的整个过程不会被打断),却无法保证之前读取myVal的操作的可见性。如果没有volatile,即使CompareExchange做了原子更新,当前线程的currVal可能还是旧值,会导致do-while循环的逻辑出错——比如明明其他线程已经更新了myVal,但当前线程还在基于旧值计算newVal,循环无法正确退出。

所以修正后的代码应该给myVal加上volatile修饰:

class MyObj {
    // 一些类代码..
    volatile int myVal; // 添加volatile修饰符
    public void foo() {
        int currVal = 0, newVal = 0;
        do {
            currVal = this.myVal;
            newVal = this.newValue(currVal);
        } while (currVal != Interlocked.CompareExchange(ref this.myVal, newVal, currVal));
    }
}

内容的提问来源于stack exchange,提问作者Ashish Negi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 08:08:24