我的想法是异步运行一些操作;我可以保证两个操作永远不会同时运行,但我不能保证它们与其他操作在同一个线程/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)
肯定会看到更新的值。
在这种情况下,锁定、易失性修饰符是完全不必要的。