C# lock关键字 同步代码块

lock关键字的作用:语句块标记为临界区,方法是获取给定对象的互斥锁,执行语句,然后释放该锁。 //来自msdn

也就是说,保证代码块同步,如:

 lock (obj)
 {
      Console.WriteLine("我是同步代码块");  //这里的同步代码块是一个同步操作,比如一个买票的操作,一个统计浏览量的操作
 }

lock来保证同步代码块(也就是上面所说的临界区)在日常的业务当中的作用不大,但是,遇到多线程的时候就显得尤为重要了,如:

日常的业务:

   static void Main(string[] args)
        {
            lockMethod();
            Console.ReadKey();
          
        }

  public static void lockMethod()
        {
                Console.WriteLine("我不是同步代码块:我现在要执行函数GetMaxId()从数据库获取最大的id,+1后做主键插入到数据库");
                Thread.Sleep(3000); //这里模拟执行执行函数GetMaxId()所需时间
                Console.WriteLine("insett GetMaxId() 的值");
        }
你看,这种情况下,lock就可有可无了,因为程序顺序执行,每次都能获取到先获取到GetMaxId()的值 再插入数据库,但是,请接着看

多线程:

  static void Main(string[] args)
        {
            Thread c1 = new Thread(lockMethod);
            Thread c2 = new Thread(lockMethod);
            Thread c3 = new Thread(lockMethod);
            c1.Start();
            c2.Start();
            c3.Start();

            Console.ReadKey();          
        }

如果启动了多线程你就会发现 你上一次获取的 GetMaxId()值还没插入数据库,另一个线程又执行GetMaxId()去数据库获取最大id,导致多线程获取的最大id是一样的
这样多个线程插入id+1后一样的话,就会报错,主键冲突

正确做法是:

 static void Main(string[] args)
        {
            Thread c1 = new Thread(lockMethod);
            Thread c2 = new Thread(lockMethod);
            Thread c3 = new Thread(lockMethod);
            c1.Start();
            c2.Start();
            c3.Start();

            Console.ReadKey();          
        }
        private static object lockObj = new object();
        public static void lockMethod()
        {
            lock (lockObj)
            {
                Console.WriteLine("我不是同步代码块:我现在要执行函数GetMaxId()从数据库获取最大的id,+1后做主键插入到数据库");
                Thread.Sleep(3000); //这里模拟执行执行函数GetMaxId()所需时间
                Console.WriteLine("insett GetMaxId() 的值");
            }
        }
这样 每次的获取操作都会等待上次操作完成,释放lockObj后才能继续执行,保证 同步

需要补充的是:

lockObj:最佳做法是定义 private 对象来锁定, 或 private static 对象变量来保护所有实例所共有的数据。//保证每次使用同一个锁

还有:

通常,应避免锁定 public 类型,否则实例将超出代码的控制范围。常见的结构 lock (this)、lock (typeof (MyType)) 和 lock ("myLock") 违反此准则:

    如果实例可以被公共访问,将出现 lock (this) 问题。

    如果 MyType 可以被公共访问,将出现 lock (typeof (MyType)) 问题。

    由于进程中使用同一字符串的任何其他代码将共享同一个锁,所以出现 lock(“myLock”) 问题。


lock (this)这种做法是微乳不推荐的做法,易造成线程死锁或其他异常

以上内容均为个人理解写出,如有错,欢迎指正!




你可能感兴趣的:(C#/.net)