程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> c# lock (obj) 與 lock (this) 區別

c# lock (obj) 與 lock (this) 區別

編輯:C#入門知識

 

 

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());

        }

1、lock(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)

 

2、lock(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)的實例

3、lock(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中的結果,也是我們不想要的。

摘自:李國清

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved