官术网_书友最值得收藏!

Locking with a Monitor construct

This recipe illustrates another common multithreaded error called a deadlock. Since a deadlock will cause a program to stop working, the first piece in this example is a new Monitor construct that allows us to avoid a deadlock. Then, the previously described lock keyword is used to get a deadlock.

Getting ready

To work through this recipe, you will need Visual Studio 2012. There are no other prerequisites. The source code for this recipe can be found at BookSamples\Chapter1\Recipe10.

How to do it...

To understand the multithreaded error deadlock, perform the following steps:

  1. Start Visual Studio 2012. Create a new C# Console Application project.
  2. In the Program.cs file, add the following using directives:
    using System;
    using System.Threading;
  3. Add the following code snippet below the Main method:
    static void LockTooMuch(object lock1, object lock2)
    {
      lock (lock1)
      {
        Thread.Sleep(1000);
        lock (lock2);
      }
    }
  4. Add the following code snippet inside the Main method:
    object lock1 = new object();
    object lock2 = new object();
    
    new Thread(() => LockTooMuch(lock1, lock2)).Start();
    
    lock (lock2)
    {
      Thread.Sleep(1000);
      Console.WriteLine("Monitor.TryEnter allows not to get stuck, returning false after a specified timeout is elapsed");
      if (Monitor.TryEnter(lock1, TimeSpan.FromSeconds(5)))
      {
        Console.WriteLine("Acquired a protected resource succesfully");
      }
      else
      {
        Console.WriteLine("Timeout acquiring a resource!");
      }
    }
    new Thread(() => LockTooMuch(lock1, lock2)).Start();
    
    Console.WriteLine("----------------------------------");
    lock (lock2)
    {
      Console.WriteLine("This will be a deadlock!");
      Thread.Sleep(1000);
      lock (lock1)
      {
        Console.WriteLine("Acquired a protected resource succesfully");
      }
    }
  5. Run the program.

How it works...

Let's start with the LockTooMuch method. In this method, we just lock the first object, wait a second and then lock the second object. Then we start this method in another thread and try to lock the second object and then the first object from the main thread.

If we use the lock keyword like in the second part of this demo, it would be a deadlock. The first thread holds a lock on the lock1 object and waits while the lock2 object gets free; the main thread holds a lock on the lock2 object and waits for the lock1 object to become free, which in this situation will never happen.

Actually, the lock keyword is a syntactic sugar for Monitor class usage. If we were to disassemble a code with lock, we would see that it turns into the following code snippet:

bool acquiredLock = false;
try
{
  Monitor.Enter(lockObject, ref acquiredLock);

// Code that accesses resources that are protected by the lock.

}
finally
{
  if (acquiredLock)
  {
    Monitor.Exit(lockObject);
  }
}

Therefore, we can use the Monitor class directly; it has the TryEnter method, which accepts a timeout parameter and returns false if this timeout parameter expires before we can acquire the resource protected by lock.

主站蜘蛛池模板: 兰考县| 南通市| 建瓯市| 鹿邑县| 建昌县| 界首市| 都兰县| 巍山| 武城县| 民乐县| 沈阳市| 永泰县| 江门市| 香格里拉县| 永康市| 莲花县| 娱乐| 丰台区| 武城县| 莒南县| 临泉县| 嘉兴市| 鸡东县| 绥中县| 石屏县| 汨罗市| 永兴县| 宣城市| 青岛市| 吉安县| 沙湾县| 东方市| 通化市| 黔西县| 濮阳市| 开化县| 庆元县| 新源县| 仙桃市| 临安市| 鄂托克旗|