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

多线程编程相对于单线程会出现一个特有的问题,就是线程安全的问题。所谓的线程安全,就是如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的。线程安全问题都是由全局变量及静态变量引起的。.

为了保证多线程情况下,访问静态变量的安全,可以用锁机制来保证,如下所示:

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  13         static void Done() 14         { 15             //lock只能锁定一个引用类型变量 16             lock (_lock) 17             { 18                 if (!_isOK) 19                 { 20                     Console.WriteLine("OK"); 21                     _isOK = true; 22                 } 23             } 24         }

单独把这个lock拿出来说下

private static object _lock = new object();

一开始我只是写成object locker = new object();

后来看了网上的代码,看了下,基本上都是private static readonly于是我就客串下百度

private:如果该实例是public,那么无关的代码也可能会锁定该对象,那就会出现多个线程等待同一个对象释放,导致死锁

static:同上,如果是公共数据类型也会出现上述问题

readonly:一旦在lock中对象值变了,那么其他线程就可以进来执行了,因为互斥锁的对象变了

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

public static class AsynAndAwait {        //step 1         private static int count = 0;        //用async和await保证多线程下静态变量count安全        public async static void M1()        {            //async and await将多个线程进行串行处理            //等到await之后的语句执行完成后            //才执行本线程的其他语句            //step 2            await Task.Run(new Action(M2));            Console.WriteLine("Current Thread ID is {0}", System.Threading.Thread.CurrentThread.ManagedThreadId);            //step 6            count++;            //step 7            Console.WriteLine("M1 Step is {0}", count);        }        public static void M2()        {            Console.WriteLine("Current Thread ID is {0}", System.Threading.Thread.CurrentThread.ManagedThreadId);            //step 3            System.Threading.Thread.Sleep(3000);            //step 4            count++;            //step 5            Console.WriteLine("M2 Step is {0}", count);        }}

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

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

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

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

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