当一次只有一个线程访问一个值时是否需要锁定?

Is locking required when only one thread accesses a value at a time?

我的想法是运行一些异步操作;我可以保证两个操作永远不会 运行 同时进行,但我不能保证它们会 运行 在同一个 thread/CPU 上。

// Example code
int myValue = 0;

ThreadPool.QueueUserWorkItem(state => {
    myValue++;

    ThreadPool.QueueUserWorkItem(state2 => {
        Console.WriteLine(myValue);
    });
});

即使没有锁定,输出也能保证1吗?

可能需要在 Console.WriteLine(myValue) 之前调用 Thread.MemoryBarrier()

或者 myValue 应该 volatile?

我不是很习惯没有锁的多线程编程,希望有人能解决我的疑惑。

谢谢!

编辑:

如果我决定使用锁定怎么办?这段代码保证输出1?

如果是,为什么?编译器不能决定将 myValue 存储在 CPU 的寄存器中吗?

我从来没有遇到过这样的代码问题,但到目前为止我只有 运行 x86 和 x64 CPU 上的程序。 MONO、ARM 和其他 "esoteric" 平台怎么样?

// Example code
object lockMe = new object();
int myValue = 0;

ThreadPool.QueueUserWorkItem(state => {
    lock(lockMe) {
        myValue++;
    }

    ThreadPool.QueueUserWorkItem(state2 => {
        lock(lockMe) {
            Console.WriteLine(myValue);
        }
    });
});

再次感谢!

ThreadPool.QueueUserWorkItem,像 任何其他在另一个线程中执行代码的库函数保证,这个 代码将看到每个修改,当前线程可见直到函数调用

因为 myValue++ 在程序顺序 ThreadPool.QueueUserWorkItem() 之前 ,调用者线程可以看到值修改的结果。所以 Console.WriteLine(myValue) 一定会看到更新后的值。

锁定,volatile修饰符在那种情况下是完全没有必要的。