当一次只有一个线程访问一个值时是否需要锁定?
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修饰符在那种情况下是完全没有必要的。
我的想法是运行一些异步操作;我可以保证两个操作永远不会 运行 同时进行,但我不能保证它们会 运行 在同一个 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修饰符在那种情况下是完全没有必要的。