是的,你需要做点什么。double
并且不能保证是 atomicdecimal
,所以如果你不保护它,你可能会得到一个撕裂的价值 - 即你的第一个子弹是完全正确的。
回复volatile
; 没有实际意义;你不能有一个volatile
字段是double
or decimal
,所以最简单的答案是:lock
。
double
失败是皇家皮塔饼;但这里有一个撕裂值示例decimal
(注意成功/失败的数量会改变每次迭代,即使数据相同;这是线程调度的随机性):
using System;
using System.Threading;
static class Program
{
private static decimal shared ;
static void Main()
{
Random random = new Random(12345);
decimal[] values = new decimal[20];
Console.WriteLine("Values:");
for (int i = 0; i < values.Length; i++)
{
values[i] = (decimal)random.NextDouble();
Console.WriteLine(values[i]);
}
Console.WriteLine();
object allAtOnce = new object();
int waiting = 10;
shared = values[0];
int correct = 0, fail = 0;
for(int i = 0 ; i < 10 ; i++)
{
Thread thread = new Thread(() =>
{
lock(allAtOnce)
{
if (Interlocked.Decrement(ref waiting) == 0)
{
Monitor.PulseAll(allAtOnce);
} else
{
Monitor.Wait(allAtOnce);
}
}
for(int j = 0 ; j < 1000 ; j++)
{
for(int k = 0 ; k < values.Length ; k++)
{
Thread.MemoryBarrier();
var tmp = shared;
if(Array.IndexOf(values, tmp) < 0)
{
Console.WriteLine("Invalid value detected: " + tmp);
Interlocked.Increment(ref fail);
} else
{
Interlocked.Increment(ref correct);
}
shared = values[k];
}
}
if (Interlocked.Increment(ref waiting) == 10)
{
Console.WriteLine("{0} correct, {1} fails",
Interlocked.CompareExchange(ref correct, 0, 0),
Interlocked.CompareExchange(ref fail, 0, 0));
Console.WriteLine("All done; press any key");
Console.ReadKey();
}
});
thread.IsBackground = false;
thread.Start();
}
}
}
关键点;该语言不保证. double
实际上,我希望你会没事的,但是线程引起的大多数微妙问题都是由于使用“我期望”而不是“我可以保证”。