浅析 C# Lock

Lock的定义以及概念

实现线程同步的第一种方式是我们经常使用的lock关键字,它将包围的语句块标记为临界区,这样一次只有一个线程进入临界区并执行代码。下面第一段的几行代码是关于lock关键字的使用方式,但更重要的是我们可以通过这个例子来看到lock关键字的本质。第二段是这个方法的IL指令集,从中可以看到lock其实也是一个语法糖,它的内部实现是采用了监视器Monitor。

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

模拟应用场景 

用多个线程同时操作一个方法,这里模拟存钱的场景。多用户(线程)操作存钱的操作。(代码如下:)

 测试使用Winform程序,一个按钮,一个RichTextBox

浅析 C# Lock_第1张图片

代码如下:

 private static object locker = new object();//定义对象
 public static int sum = 0; //总账户余额

 //存钱的业务逻辑
  private void addToSum()
        {
            lock (locker)//加锁
            {
                while (true)
                {
                    richTextBox1.Invoke(new Action((x) =>
                    {
                        richTextBox1.AppendText("正在存钱" + x);
                        sum += 100;
                        //Thread.Sleep(TimeSpan.FromMilliseconds(2000)); //此处是占用了主线程,会导致UI卡着不动,刷新迟缓。所以卸载Invoke外层去了,不信可以用下面的if做下测试
                        richTextBox1.AppendText("当前余额为" + sum + "\r\n");
                        System.Windows.Forms.Application.DoEvents();
                    }), Thread.CurrentThread.Name);
                    // if (sum >= 1000) { break; }
                    Thread.Sleep(TimeSpan.FromMilliseconds(2000));
                }
            }
        }

下面来操作这个账户,声明多个线程来操作这个方法。看下执行效果。

  private void button1_Click(object sender, EventArgs e)
        {
            Thread th1 = new Thread(addToSum);
            th1.Name = "th1name";//指定线程名称,方便区分
            Thread th2 = new Thread(addToSum);
            th1.Start();
            Thread.Sleep(1000);
            th2.Start();
        }

分两种情况来解析

第一种是,加锁的情况下

lock (locker)//加锁

第二种是将这段代码块注释掉,分别看下执行效果。

//lock (locker)//加锁  注释掉

执行结果如下:加锁

浅析 C# Lock_第2张图片

不加锁:

浅析 C# Lock_第3张图片

 

以上为执行结果,可以看出,加锁与不加锁的情况下,执行结果显然不同。

欢迎大家指正。感谢。

更多博文,请点击下方链接,共同学习,共同进步。

C#设计模式,工厂三兄弟

你可能感兴趣的:(C#,Lock,多线程,Winform,C#面向对象,多线程)