class Program
{
private static volatile int value;
public static void Increment()
{
for (int i =0; i <100000; i++)
{
value++;
}
}
public static void Decrement()
{
for (int j =0 ; j < 100000; j++)
{
value--;
}
}
public static void ThreadTest()
{
value = 0;
var incrementThread = new Thread(Increment);
var decrementThread = new Thread(Decrement);
incrementThread.Start();
decrementThread.Start();
incrementThread.Join();
decrementThread.Join();
Console.WriteLine("Value of value {0}", value);
}
static void Main(string[] args)
{
ThreadTest();
}
}
答案 0 :(得分:17)
因为它不应该...... ++和 - 不是原子操作(不像Interlocked.XXXX opreations - Interlocked.Increment)。
如果你写下++和 - 的每一步,并看看两者如何通过不同的线程混合,你会明白为什么:
增量
1: load value to temp
2: add temp, 1
3: store temp to value
递减
4: load value to temp2
5: substruct temp2, 1
6: store temp2 to value
因此,如果订单是1,2,3,4,5,6,则得到值= 0;但如果订单是1,2,4,5,6,3,则得到值= 1.
答案 1 :(得分:1)
只是试图让事情更简单......我也在当天回击了这个问题:D
易失性确保您读取最新值,并且当您编写所有线程时看到该新值(这是易失性操作的用途),但它不能确保读取和写入之间,其他线程不是要修改价值。另一方面,Interlocked(提供原子操作)确实可以确保它。
当例如线程或线程读取和其他修改时,易失性操作是好的。例如,如果你的类中有一个volatile Boolean _disposed
标志,那么如果一个线程处理它,它会被标记为立即为所有线程处理。