c# lock (obj) 与 lock (this) 区别

lock(obj) 锁定obj 对象

lock(this) 锁定 当前实例对象,如果有多个类实例的话,lock锁定的只是当前类实例,对其它类实例无影响。

直接上代码。

主窗体代码如下:

delegate void SetTextCallback(string text);

        public Form1()

        {

            InitializeComponent();

        }

        /// <summary>

        /// 利用委托设置 文本框内容

        /// </summary>

        /// <param name="text"></param>

        public void SetText(string text)

        {

            if (this.textBox1.InvokeRequired)

            {

                SetTextCallback d = new SetTextCallback(SetText);

                this.Invoke(d, new object[] { text });

            }

            else

            {

                this.textBox1.Text = this.textBox1.Text + "\r\n" + text;

            }

        }

 

        private void button1_Click(object sender, EventArgs e)

        {

            textBox1.Text = "";

            Thread[] thd = new Thread[500];

            int intI = 0;

            for (intI = 0; intI < 50; intI++)

            {

                thd[intI] = new Thread(new ParameterizedThreadStart(thdText));

                thd[intI].Name = " Thread" + intI.ToString();

                thd[intI].IsBackground = true;

                thd[intI].Start(intI);

            }

        }

        /// <summary>

        /// 线程调用的方法

        /// </summary>

        /// <param name="obj"></param>

        private void thdText(object obj)

        {

            oper op = new oper();

            int intI = Convert.ToInt32(obj);

            SetText(op.addition());

        }

1lock(obj)

添加oper类,代码如下:

    public class oper

    {

        private static object obj = new object();

 

        private static Single slgTotal;

 

        public string addition()

        {

            lock (obj)

            {

                int intI = 0;

                slgTotal = 0;

                for (intI = 0; intI <= 50; intI++)

                {

                    slgTotal = slgTotal + intI;

                    Thread.Sleep(5);

                }

 

                return slgTotal.ToString() + " thread:" + Thread.CurrentThread.Name;

            }

        }

    }

执行结果如下:

\

大家看到每个线程执行的结果都是相同的。下面来看lock(this)

 

2lock(this)

将oper类代码修改为如下:

    public class oper

    {

        private static object obj = new object();

 

        private static Single slgTotal;

 

        public string addition()

        {

            lock (this)

            {

                int intI = 0;

                slgTotal = 0;

                for (intI = 0; intI <= 50; intI++)

                {

                    slgTotal = slgTotal + intI;

                    Thread.Sleep(5);

                }

 

                return slgTotal.ToString() + " thread:" + Thread.CurrentThread.Name;

            }

        }

    }

执行结果如下:

\

大家看到每个线程执行的结果都是不同的。

分析:lock(this) 锁定的对象 是当前类实例,而每个线程操作的都是oper的新实例,lock(this)只对当前实例起作用,而slgTotal 是类的静态变量,lock(this)实际上是没在起起我们想要的结果。下面再看一种lock(obj)的实例

3lock(obj) 这个第一个obj的demo稍有不同,即把oper类的obj静态变量修改为变量,oper类修改为如下:

    public class oper

    {

        private object obj = new object();

 

        private static Single slgTotal;

 

        public string addition()

        {

            lock (obj)

            {

                int intI = 0;

                slgTotal = 0;

                for (intI = 0; intI <= 50; intI++)

                {

                    slgTotal = slgTotal + intI;

                    Thread.Sleep(5);

                }

 

                return slgTotal.ToString() + " thread:" + Thread.CurrentThread.Name;

            }

        }

    }

执行结果如下:

\

此次运行结果和lock(this)结果是一样的。这是为什么呢?

总结:其实大家不要去看lock中锁定的是this,还是obj,大家只要关心多线程锁定的对象是不是为同一个对象。如果是同一个对象则会得到如上边的demo1结果,否则则如demo2和demo3中的结果,也是我们不想要的。

摘自:李国清

原文地址:https://www.cnblogs.com/rinack/p/3101577.html