我正在看一个关于p的例子。斯蒂芬克莱里的40本书是
IFrequency
我有点困惑为什么需要// Note: this is not the most efficient implementation.
// This is just an example of using a lock to protect shared state.
static int ParallelSum(IEnumerable<int> values)
{
object mutex = new object();
int result = 0;
Parallel.ForEach(source: values,
localInit: () => 0,
body: (item, state, localValue) => localValue + item,
localFinally: localValue =>
{
lock (mutex)
result += localValue;
});
return result;
}
。因为如果我们所做的只是总结lock
的集合,比如说int
,那么我们就不需要关心以任何顺序递增的共享和{1, 5, 6}
。
result
有人可以解释我的思想存在缺陷吗?
我想我对方法的身体有点困惑不能简单地
(1 + 5) + 6 = 1 + (5 + 6) = (1 + 6) + 5 = ...
答案 0 :(得分:10)
添加等操作不是 atomic ,因此不是线程安全的。在示例代码中,如果省略了锁,则完全有可能在几乎同时执行两个加法运算,导致其中一个值被覆盖或错误地添加。有一种 线程安全的方法可以增加整数:.text-shop-button {
-fx-text-fill: white;
-fx-background-image: url("../resources/Game/button.png");
-fx-min-height: 40px;
-fx-min-width: 120px;
-fx-max-height: 40px;
-fx-max-width: 120px;
-fx-focus-color: transparent;
-fx-faint-focus-color: transparent;
-fx-background-position: center;
}
.text-shop-button:pressed {
-fx-min-height: 36px;
-fx-min-width: 108px;
-fx-max-height: 36px;
-fx-max-width: 108px;
-fx-font-size: 90%;
-fx-background-position: center;
-fx-background-size: 90%;
}
。但是,由于没有使用,因此在示例代码中需要锁定以确保一次完成一个非原子加法操作(按顺序而不是并行)。
答案 1 :(得分:7)
它不是关于'result'更新的顺序,更新它的race condition,记住运算符+=
不是原子的,所以两个线程可能看不到另一个线程的udpate在他们触摸它之前
答案 2 :(得分:3)
语句result += localValue;
实际上是在说result = result + localValue;
您正在阅读和更新由不同线程共享的资源(变量)。这很容易导致竞争条件。 lock
确保在任何给定时刻该语句由单个线程访问。