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

时间:2015-11-10 06:54:52

标签: c# multithreading lock-free

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

// Example code
int myValue = 0;

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

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

即使没有锁定,输出仍保证为1吗?

也许在Thread.MemoryBarrier()之前需要拨打Console.WriteLine(myValue)

或者myValue可能会成为volatile

我不习惯没有锁定的多线程编程,我希望有人可以解决我的疑虑。

谢谢!

修改

如果我决定使用锁定怎么办?此代码是否保证输出1

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

我从来没有遇到像这样的代码有任何问题,但到目前为止我只在x86和x64 CPU上运行我的程序。那么MONO,ARM和其他“深奥”平台呢?

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

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

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

再次感谢!

1 个答案:

答案 0 :(得分:1)

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

由于myValue++在程序顺序之前位于ThreadPool.QueueUserWorkItem() ,因此调用程序线程会看到值的修改结果。所以Console.WriteLine(myValue)肯定会看到更新的价值。

在这种情况下,完全没有锁定,易失性修饰符。