用简单的C#重现线程死锁

时间:2013-09-27 17:36:08

标签: c# multithreading

我想我遇到了死锁的问题......我的程序运行良好,但有时候它没有反应...... ??? 在源代码(C#)..没有锁(objet)或ReaderWriterLockSlim ... 我确实试图用2个线程使用相同的对象(List)重现死锁但没有成功..

int n = 0;                      
  List<int> temp = new List<int>();
  var up = new Thread(() =>{
     for (int i = 0; i < 100000; i++){
     n++;
     temp.Add(i);                   
}
});

var down = new Thread(() => {
    for (int i = 0; i < 100000; i++){
        n--;
         try{
           temp.Remove(i);
         }catch {
           Console.WriteLine("No item {0} to remove", i);
         }
        }
});

up.Start();
down.Start();
down.Join();
up.Join();
Console.WriteLine(String.Join(",",temp));

上面的狙击代码仍可正常运行而无死锁.. ??? 有人可以帮我用2个线程重复死锁,使用相同的变量而没有锁(对象)或系统锁...

先谢谢

2 个答案:

答案 0 :(得分:3)

List不是线程安全的,因此这将是您的问题的原因。您应该创建一个线程安全的解决方案(使用lock或使用线程安全的集合),而不是专注于重新创建死锁。那会告诉你什么?

答案 1 :(得分:1)

通常在使用锁定或同步时会发生死锁。

最常见的死锁是从一个线程更新Gui。像:

Thread thread = new Thread( () => 
{ 
    Invoke(new Action(() => 
    {
        Label1.Text = "something";
    }));
});

thread.Start();

// this join will prevent the messageloop from running, but the invoke waits on the messageloop to execute it's action.
thread.Join();

但它不像你的情况。

我认为你的意思是n在不同的线程上增加和减少(与变更列表相同)。这不是死锁,而是 threadsafety 问题。

即使你锁定它,你也不会陷入僵局。

object lockObj = new object();

 var up = new Thread(() =>
 {
     for (int i = 0; i < 100000; i++)
     {
         lock(lockObj)
         {
             n++;
             temp.Add(i);                   
         }
     }
 });

 var down = new Thread(() => 
 {
     for (int i = 0; i < 100000; i++)
     {
         lock(lockObj)
         {
             n--;
             try
             {
                 temp.Remove(0);
             }
             catch 
             {
                 Console.WriteLine("No item {0} to remove", i);
             }
         }
     }
});

但这会大大减缓这个过程。