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



我的想法是异步运行一些操作;我可以保证两个操作永远不会同时运行,但我不能保证它们与其他操作在同一个线程/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和其他"深奥"的平台呢?

// 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)肯定会看到更新的值。

在这种情况下,锁定、易失性修饰符是完全不必要的。

相关内容

  • 没有找到相关文章

最新更新