2015-10-21 77 views
1

我是多线程新手。我试图锁定对象时,它被另一个线程锁定,我期待一个错误,并尝试使用异常,但它没有奏效。尝试锁定对象时尝试/捕获

class Program 
    { 
     static readonly object lockNum = new object(); 
     static int A = 10; 

     public static void Thread1() 
     { 
      lock (lockNum) 
      { 
       A = 100; 
       Console.WriteLine(A); 
      } 
     } 

     public static void Thread2() 
     { 
      Thread.Sleep(1000); 
      lock (lockNum) 
      { 
       Thread.Sleep(9000); 
       Console.WriteLine(A); 
       Console.WriteLine("Thread 2 is executed"); 
      } 
     } 

     public static void Thread3() 
     { 
      Thread.Sleep(3000); 

      try 
      { 
       lock (lockNum) 
       { 
        Console.WriteLine(A); 
        Console.WriteLine("Thread 3 is executed"); 
       } 
      } 
      catch (Exception ex) 
      { 
       Console.WriteLine("Object is locked"); 
      } 

     } 

    } 

    public class MyClass 
    { 

     public static void Main() 
     { 
      Thread tid1 = new Thread(new ThreadStart(Program.Thread1)); 
      Thread tid2 = new Thread(new ThreadStart(Program.Thread2)); 
      Thread tid3 = new Thread(new ThreadStart(Program.Thread3)); 

      tid1.Start(); 
      tid2.Start(); 
      tid3.Start(); 

      Console.ReadLine(); 
     } 
    } 

的线程2和Thread3在Thread.Sleep(9000);我希望有3秒后的异常,因为对象是否仍然由线程2锁定后一起运行。我正在尝试使Thread3再次睡眠3秒,以检查对象是否已解锁(可能是WriteLine错误)并重复,直到对象被解锁。

回答

2

锁不会抛出异常,他们只是等到另一个线程释放了锁。

如果你想如果lock不能声称跳过代码,你可以使用

if (Monitor.TryEnter(lockNum)) 
{ 
    Console.WriteLine("No one else had the lock, now it's mine!"); 
} 
else 
{ 
    Console.WriteLine("Another thread won :("); 
} 

您可以选择提供超时该方法。

+0

非常感谢你的解释。 – Mirza

+1

这不是锁定的完整故事。如果你使用'Monitor.TryEnter'而不是'lock()',你也需要手动释放这个锁,如果'TryEnter'成功的话,使用'Monitor.Exit(lockNum)'。这意味着您应该使用try-finally块来确保在出现异常时调用Monitor.Exit。微软的[示例代码在这里](https://msdn.microsoft.com/en-us/library/4tssbxcw(v = vs.110).aspx) - 这几乎是安全的,但Eric Lippert指出[这里]( https://blogs.msdn.microsoft.com/ericlippert/2009/03/06/locks-and-exceptions-do-not-mix/)甚至可能会出错。 – Jenesis

2

您的代码应该是这样的:

public static void Thread3() 
    { 
     Thread.Sleep(3000); 

     try 
     { 
      if (Monitor.TryEnter(lockNum)) 
      { 
       Console.WriteLine(A); 
       Console.WriteLine("Thread 3 is executed"); 
      } 
      else throw new Exception(); 
     } 
     catch (Exception ex) 
     { 
      Console.WriteLine("Object is locked"); 
     } 

    } 

EDIT1:啊...的解释是由其他人提供,

EDIT2:其实这不是来处理它的最佳方式。例外很重。你可以摆脱try catch块,而不是抛出异常,你可以打印出你的消息。

+0

你也帮了很多。谢谢 :) – Mirza