深入分析C# 线程同步

2020-06-17 15:01:08于丽

同步对象可以兼作它lock的对象

如:

class ThreadSafe
{
 private List <string> _list = new List <string>(); 
 void Test()
 {
 lock (_list)
 {
 _list.Add ("Item 1");
 }
 }
}

Monitors

lock其实是Monitors的简洁写法。

lock (x) 
{ 
 DoSomething(); 
} 

两者其实是一样的。

System.Object obj = (System.Object)x; 
System.Threading.Monitor.Enter(obj); 
try 
{ 
 DoSomething(); 
} 
finally 
{ 
 System.Threading.Monitor.Exit(obj); 
} 

互斥锁(Mutex)

互斥锁是一个互斥的同步对象,同一时间有且仅有一个线程可以获取它。可以实现进程级别上线程的同步。

class Program
 {
 //实例化一个互斥锁
 public static Mutex mutex = new Mutex();

 static void Main(string[] args)
 {
  for (int i = 0; i < 3; i++)
  {
  //在不同的线程中调用受互斥锁保护的方法
  Thread test = new Thread(MutexMethod);
  test.Start();
  }
  Console.Read();
 }

 public static void MutexMethod()
 {
  Console.WriteLine("{0} 请求获取互斥锁", Thread.CurrentThread.Name);
  mut.WaitOne();
  Console.WriteLine("{0} 已获取到互斥锁", Thread.CurrentThread.Name); 
  Thread.Sleep(1000);
  Console.WriteLine("{0} 准备释放互斥锁", Thread.CurrentThread.Name);
  // 释放互斥锁
  mut.ReleaseMutex();
  Console.WriteLine("{0} 已经释放互斥锁", Thread.CurrentThread.Name);
 }
 }

互斥锁可以在不同的进程间实现线程同步

使用互斥锁实现一个一次只能启动一个应用程序的功能。

 public static class SingleInstance
 {
 private static Mutex m;

 public static bool IsSingleInstance()
 {
  //是否需要创建一个应用
  Boolean isCreateNew = false;
  try
  {
  m = new Mutex(initiallyOwned: true, name: "SingleInstanceMutex", createdNew: out isCreateNew);
  }
  catch (Exception ex)
  {
  
  }
  return isCreateNew;
 }
 }

互斥锁的带有三个参数的构造函数

initiallyOwned: 如果initiallyOwned为true,互斥锁的初始状态就是被所实例化的线程所获取,否则实例化的线程处于未获取状态。 name:该互斥锁的名字,在操作系统中只有一个命名为name的互斥锁mutex,如果一个线程得到这个name的互斥锁,其他线程就无法得到这个互斥锁了,必须等待那个线程对这个线程释放。 createNew:如果指定名称的互斥体已经存在就返回false,否则返回true。

信号和句柄

lockmutex可以实现线程同步,确保一次只有一个线程执行。但是线程间的通信就不能实现。如果线程需要相互通信的话就要使用AutoResetEvent,ManualResetEvent,通过信号来相互通信。它们都有两个状态,终止状态和非终止状态。只有处于非终止状态时,线程才可以阻塞。