线程、任务和同步学习笔记(六)
1、如前所述,lock语句由编译器解析为Monitor类。Monitor类是一个静态类,有Enter和Exit方法。
1 using System; 2 using System.Text; 3 using System.Threading; 4 using System.Threading.Tasks; 5 6 class Program 7 { 8 static void Main(string[] args) 9 { 10 StringBuilder str = new StringBuilder(); 11 new Task(() => 12 { 13 for (int i = 0; i < 26; i++) 14 { 15 str.Append(((char)('A' + i)).ToString()); 16 } 17 str.Append("\n"); 18 }).Start(); 19 new Thread(() => 20 { 21 for (int i = 0; i < 26; i++) 22 { 23 str.Append(((char)('a' + i)).ToString()); 24 } 25 str.Append("\n"); 26 }).Start(); 27 Console.WriteLine(str); 28 Console.WriteLine("End the main thread."); 29 } 30 }
运行结果:
将上述代码修改如下:
1 using System; 2 using System.Text; 3 using System.Threading; 4 using System.Threading.Tasks; 5 6 class Program 7 { 8 static void Main(string[] args) 9 { 10 object locker = new object(); 11 StringBuilder str = new StringBuilder(); 12 new Task(() => 13 { 14 lock (locker) 15 { 16 for (int i = 0; i < 26; i++) 17 { 18 str.Append(((char)('A' + i)).ToString()); 19 } 20 } 21 Console.WriteLine("{0} in thread {1}", str, Thread.CurrentThread.ManagedThreadId); 22 }).Start(); 23 new Thread(() => 24 { 25 lock (locker) 26 { 27 for (int i = 0; i < 26; i++) 28 { 29 str.Append(((char)('a' + i)).ToString()); 30 } 31 } 32 Console.WriteLine("{0} in thread {1}", str, Thread.CurrentThread.ManagedThreadId); 33 }).Start(); 34 Console.WriteLine("End the main thread."); 35 } 36 }
运行结果:
使用Monitor类再一次将上述代码做如下修改:
1 using System; 2 using System.Text; 3 using System.Threading; 4 using System.Threading.Tasks; 5 6 class Program 7 { 8 static void Main(string[] args) 9 { 10 object locker = new object(); 11 StringBuilder str = new StringBuilder(); 12 new Task(() => 13 { 14 while (true) 15 { 16 Monitor.Enter(locker); 17 try 18 { 19 for (int i = 0; i < 26; i++) 20 { 21 str.Append(((char)('A' + i)).ToString()); 22 } 23 str.Append("\n"); 24 Console.WriteLine("{0} in thread {1}", str.ToString(), Thread.CurrentThread.ManagedThreadId); 25 } 26 finally 27 { 28 Monitor.Exit(locker); 29 } 30 } 31 }).Start(); 32 new Thread(() => 33 { 34 while (true) 35 { 36 Monitor.Enter(locker); 37 try 38 { 39 for (int i = 0; i < 26; i++) 40 { 41 str.Append(((char)('a' + i)).ToString()); 42 } 43 str.Append("\n"); 44 Console.WriteLine("{0} in thread {1}", str.ToString(), Thread.CurrentThread.ManagedThreadId); 45 } 46 finally 47 { 48 Monitor.Exit(locker); 49 } 50 } 51 }).Start(); 52 Console.WriteLine("End the main thread."); 53 } 54 }
运行结果:
2、从运行结果可以看出,使用Monitor类可以完全取代lock语句。Monitor类的优势是可以使用TryEnter方法,该方法可以传递一个被锁定的超时值,从而避免无限等待,即避免死锁的现象发生。
1 using System; 2 using System.Text; 3 using System.Threading; 4 using System.Threading.Tasks; 5 6 class Program 7 { 8 static void Main(string[] args) 9 { 10 object locker = new object(); 11 new Thread(() => 12 { 13 Random random = new Random(); 14 bool locked = false; 15 Monitor.TryEnter(locker, 200, ref locked); 16 if (locked) 17 { 18 try 19 { 20 while (true) 21 { 22 int i = random.Next(5); 23 Thread.Sleep(i); 24 Console.WriteLine("{0} in thread {1}, {2}", DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss.fff"), Thread.CurrentThread.ManagedThreadId, i); 25 } 26 } 27 finally 28 { 29 Monitor.Exit(locker); 30 } 31 } 32 else 33 { 34 Console.WriteLine("Not locked int thread {0}", Thread.CurrentThread.ManagedThreadId); 35 } 36 }).Start(); 37 new Thread(() => 38 { 39 Random random = new Random(); 40 bool locked = false; 41 Monitor.TryEnter(locker, 200, ref locked); 42 if (locked) 43 { 44 try 45 { 46 while (true) 47 { 48 int i = random.Next(5); 49 Thread.Sleep(i); 50 Console.WriteLine("{0} in thread {1}, {2}", DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss.fff"), Thread.CurrentThread.ManagedThreadId, i); 51 } 52 } 53 finally 54 { 55 Monitor.Exit(locker); 56 } 57 } 58 else 59 { 60 Console.WriteLine("Not locked int thread {0}", Thread.CurrentThread.ManagedThreadId); 61 } 62 }).Start(); 63 } 64 }
运行结果:
3、SpinLock结构是.NET4新增的,其用法与Monitor类相似。
4、WaitHandle类是一个抽象类,可以等待一个信号的设置,因为它是基类,可以派生出多个类,可以等待不同的信号。