zoukankan      html  css  js  c++  java
  • 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);
            }
    }

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

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

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

  • 相关阅读:
    SQL Data Services Abandons REST for TDS API and Knocks My Socks Off
    C# Lambda Expressions 简介
    Web.config 和 App.config 区别
    XPO 第三方控件学习(DevExpress Persistent Object )系列查询
    进销存管理系统 系列
    MOSS 学习系列(十万个为什么)--为什么我要定制审批流程的时候找不到审批的选项?
    XPO 第三方控件学习(DevExpress Persistent Object )系列 其他(session,事务,有效性检查...
    如何使用三态工作流(一)
    english interview example
    How to build a K2 SharePoint Workflow(2)
  • 原文地址:https://www.cnblogs.com/qinyi173/p/11421834.html
Copyright © 2011-2022 走看看