我可能在这里缺少一些基本的知识,但仍然希望您能帮助您理解这一点。因此,我编写了以下简单的多线程程序:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
// List<int> outcome = new List<int>();
Test t = new Test();
Thread thread1 = new Thread(new ThreadStart(t.call1));
Thread thread2 = new Thread(new ThreadStart(t.call2));
thread1.Start();
thread2.Start();
Thread.Sleep(3000); //Give enough time for threads to end
Console.Write("{0},", t.mSum);
t.mSum = 0;
}
}
class Test
{
public int mSum = 0;
public void call1()
{
//lock (this)
//{
for (int i = 0; i < 100; i++)
{
Console.WriteLine("Hello Thread 1, mSum value: {0}", mSum);
mSum = mSum + 1;
Console.WriteLine("Goodbye Thread 1, mSum value: {0}", mSum);
}
//}
// Console.WriteLine(mSum);
}
public void call2()
{
for (int i = 0; i < 100 ; i++)
{
Console.WriteLine("Hello Thread 2, mSum value: {0}",mSum);
mSum = mSum + 1;
Console.WriteLine("Goodbye Thread 2, mSum value: {0}",mSum);
}
}
}
}
因此,我希望此输出是不确定的,因为上下文切换可以随时发生,对吗?但是,当我运行该程序时,我得到以下输出(由于我的stackoverflow.com问题发布技能不佳,输出中只有一部分是畸形的):
Hello线程1,mSum值:62再见线程1,mSum值:63 Hello线程1,mSum值:63再见线程1,mSum值:64 Hello线程2,mSum值:59再见线程2,mSum值:65 你好线程2,mSum值:65再见线程2,mSum值:66
因此,假设我没有写错,并且确实在线程之间共享了mSum(看起来像...)-如何解释行号。3?线程2读为59,加1,然后得到65!
我发现了一种新的数学方法吗?:)
您不是在锁定共享变量mSum
,mSum = mSum + 1
也不是原子操作。很明显,打印到控制台,增加一个变量然后再次打印到控制台不再是原子的:)有许多种可能的线程交织方式。例如:
1)mSum = 0 [Thread1正在运行]
2)mSum = 1 [线程1正在运行]
3)mSum = 2 [Thread2正在运行]
4)...
5)mSum = 59 [Thread2正在运行],并且在“ Hello ...”之后被抢占
6)mSum = 60 [线程1正在工作]
7)mSum = 61 [线程1正在运行]
8)...
9)mSum = 64 [Thread2正在运行]在增量线Thread2继续之前唤醒,并计算65
在5)
Thread2
甚至可以从内存中读取MSUM后已经捷足先登mSum = mSum + 1
,但在计算前mSum + 1
。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句