01月07th

在多线程下C#如何保证线程安全

DIY编程技术4385℃我来说两句!
多线程编程相对于单线程会出现一个特有的问题,就是线程安全的问题。所谓的线程安全,就是如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的。 线程安全问题都是由全局变量及静态变量引起的。
  为了保证多线程情况下,访问静态变量的安全,可以用锁机制来保证,如下所示:
  1. //需要加锁的静态全局变量

  2.         private static bool _isOK = false;

  3.         //lock只能锁定一个引用类型变量

  4.         private static object _lock = new object();

  5.         static void MLock()

  6.         {

  7.             //多线程

  8.             new System.Threading.Thread(Done).Start();

  9.             new System.Threading.Thread(Done).Start();

  10.             Console.ReadLine();

  11.         }

  12.         static void Done()

  13.         {

  14.             //lock只能锁定一个引用类型变量

  15.             lock (_lock)

  16.             {

  17.                 if (!_isOK)

  18.                 {

  19.                     Console.WriteLine("OK");

  20.                     _isOK = true;

  21.                 }

  22.             }

  23.         }

复制代码

需要注意的是,Lock只能锁住一个引用类型的对象。另外,除了锁机制外,高版本的C#中加入了async和await方法来保证线程安全,如下所示:

  1. public static class AsynAndAwait

  2. {

  3.         //step 1 

  4.         private static int count = 0;

  5.         //用async和await保证多线程下静态变量count安全

  6.         public async static void M1()

  7.         {

  8.             //async and await将多个线程进行串行处理

  9.             //等到await之后的语句执行完成后

  10.             //才执行本线程的其他语句

  11.             //step 2

  12.             await Task.Run(new Action(M2));

  13.             Console.WriteLine("Current Thread ID is {0}", System.Threading.Thread.CurrentThread.ManagedThreadId);

  14.             //step 6

  15.             count++;

  16.             //step 7

  17.             Console.WriteLine("M1 Step is {0}", count);

  18.         }


  19.         public static void M2()

  20.         {

  21.             Console.WriteLine("Current Thread ID is {0}", System.Threading.Thread.CurrentThread.ManagedThreadId);

  22.             //step 3

  23.             System.Threading.Thread.Sleep(3000);

  24.             //step 4

  25.             count++;

  26.             //step 5

  27.             Console.WriteLine("M2 Step is {0}", count);

  28.         }

  29. }

复制代码

在时序图中我们可以知道,共有两个线程进行交互,如下图所示:

 
用async和await后,上述代码的执行顺序为下图所示:

 
若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时对一个变量执行读写操作,一般都需要考虑线程同步,否则就可能影响线程安全

本文出自:DIY博客园,链接:https://www.diybloghome.com/prology/1058.html,转载请注明!