C# 多线程中的常见问题
1. 资源竞争 当多个同时执行的线程需要同时对全局变量进行写读操作时,容易出现资源竞争的问题,导致运行结果出现多种情况。以下面的例子进行说明: ? private static CancellationTokenSource cs = new CancellationTokenSource(); private static int num = 5; private static object obj = new object(); static void Main(string[] args) { Console.WriteLine("Main Start...."); Task t1 = Task.Factory.StartNew(Test); Task t2 = Task.Factory.StartNew(Test); Task.WaitAll(new Task[] { t1,t2 }); cs.Dispose(); Console.WriteLine("Main end...."); Console.ReadLine(); } static void Test() { while (!cs.IsCancellationRequested) //是否调用Cancel { Console.WriteLine("TaskId {0} Excute other code....num is {1}",Task.CurrentId,num); if(num == 5){ Thread.Sleep(50); //为了方便观察,添加延时 num++; Console.WriteLine("TaskId {0} and Num is {1}",num); if (!cs.IsCancellationRequested) { cs.Cancel(); //取消操作 } } } } ?大多数情况,运行结果如下: Main Start.... 任务1 首先运行至Thread.Sleep(50),等待50ms,cpu开始调度任务2运行至Thread.Sleep(50)。 接着任务1 运行num++,并往控制台输出结果num=6,然后任务2运行num++,并往控制台输出num=7。但有时也会出现下面这种结果: Main Start.... 任务1 首先运行至Thread.Sleep(50),等待50ms,cpu开始调度任务2运行至Thread.Sleep(50)。接着任务1 运行num++,cpu马上开始调度任务2运行num++,并往控制台输出num=7,最后调度任务1往控制台输出num=7。 ?解决方式:只需加上线程锁lock,便只会出现第一种运行结果,如下: static void Test() { while (!cs.IsCancellationRequested) //是否调用Cancel { Console.WriteLine("TaskId {0} Excute other code....num is {1}",num); if(num == 5){ Thread.Sleep(50); //为了方便观察,添加延时 lock (obj) //只有一个线程可以操作 { num++; Console.WriteLine("TaskId {0} and Num is {1}",num); } if (!cs.IsCancellationRequested) { cs.Cancel(); //取消操作 } } } } ?2.线程死锁 至少有2个线程被挂起,等待对方解锁,线程将无限等待下去。 ? private static int num = 5; private static object obj1 = new object(); private static object obj2 = new object(); static void Main(string[] args) { Console.WriteLine("Main Start...."); Parallel.Invoke(LockTest1,LockTest2); Console.WriteLine("Main end...."); Console.ReadLine(); } static void LockTest1() { lock(obj1){ lock(obj2){ Console.WriteLine("LockTest1 is running"); } } } static void LockTest2() { lock (obj2) { lock (obj1) { Console.WriteLine("LockTest2 is running"); } } } ? 运行结果: Main Start.... 看似正常,但这段程序在极少数的情况下,会出现死锁。例如CPU先运行LockTest1()中lock(obj1),马上又运行LockTest2()中lock(obj2),这时LockTest1()会等待obj2 解锁,而LockTest2()会等待obj1解锁 ,形成死锁。 ? 解决方式:在设计程序时,考虑好锁定的顺序,或者定义锁定超时。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |