c#中多线程同步Lock(锁)的研究以及跨线程UI的操做 (转)

https://www.cnblogs.com/tommyheng/p/4104552.htmlhtml

本文只针对C#中,多线程同步所用到的锁(lock)做为研究对象。因为想更直观的显示结果,因此,在作demo的时候,就把多线程经过事件操做UI的代码也写了出来,留做备忘和分享吧。多线程

 

其实多线程的同步,使用同步锁的方法用了好屡次,今天无心中看到MSDN中,建议用:并发

1 private static readonly object locker1 = new object(); 2 private readonly object locker2 = new object();

备注:原文并无加readonly,是我后来本身加进去的。测试

我不只思考了一下他们的区别。this

而后我写了一段代码进行测试,测试类代码以下:spa

复制代码
    /// <summary> /// 跨线程操做UI的时候传递的参数,本文为了显示消息,因此简单的封装了一个 /// </summary> public class MyEventArgs : EventArgs { public readonly string Message = string.Empty; public MyEventArgs(string msg) { this.Message = msg; } } /// <summary> /// 测试类,用于测试2种锁的区别 /// </summary> public class LockTest { //2个锁 private static readonly object Locker1 = new object(); private readonly object Locker2 = new object(); /// <summary> /// 跨线程操做UI的委托和事件 /// </summary> public delegate void MessageEventHandler(object sender, MyEventArgs e); public event MessageEventHandler MessageEvent; public void OnMessage(MyEventArgs e) { if (this.MessageEvent != null) MessageEvent(this, e); } //要锁的变量,经过它能够看出2种锁在不一样状况下的效果 private int num = 0; //实例名字 private readonly string Name; public LockTest(string name) { Name = name; } //第一种锁执行的方法 public void AddNum1() { lock (Locker1) { num = 0; ShowMessage(); } } //第二种锁执行的方法 public void AddNum2() { lock (Locker2) { num = 0; ShowMessage(); } } //锁内的一些操做,并经过事件,把关键的消息显示到主线程中的UI里 private void ShowMessage() { string msg = ""; for (int i = 0; i < 10; i++) { num += 1; msg = string.Format("线程 [{0}],实例[{1}]中num的值是[{2}]", Thread.CurrentThread.Name, this.Name, num); OnMessage(new MyEventArgs(msg)); Thread.Sleep(100); } msg = string.Format("======线程 [{0}]执行完毕======", Thread.CurrentThread.Name); OnMessage(new MyEventArgs(msg)); } }
复制代码

测试用的类写完了,开始测试:线程

首先测试单个实例、多线程,2种锁的区别:3d

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
private void button1_Click( object sender, EventArgs e)
{
     LockTest test = new LockTest( "LockTest 1" );
     test.MessageEvent += new LockTest.MessageEventHandler(MessageCallBack);
     listBox1.Items.Clear();
     for ( int i = 0; i <= 2; i++)
     {
         Thread a = new Thread( new ThreadStart(test.AddNum1));
         a.Name = i.ToString();
         a.Start();
     }
}
 
private void button2_Click( object sender, EventArgs e)
{
     LockTest test = new LockTest( "LockTest 1" );
     test.MessageEvent += new LockTest.MessageEventHandler(MessageCallBack);
     listBox1.Items.Clear();
     for ( int i = 0; i <= 2; i++)
     {
         Thread a = new Thread( new ThreadStart(test.AddNum2));
         a.Name = i.ToString();
         a.Start();
     }
}

  输出结果如出一辙:
code

得出结论:若是对一个实例,多线程访问的时候,2种锁是没有区别的。orm

下面是测试多个实例的状况(静态锁):

复制代码
        private void button3_Click(object sender, EventArgs e) { listBox1.Items.Clear(); for (int i = 0; i <= 2; i++) { LockTest test = new LockTest("LockTest " + i.ToString()); test.MessageEvent += new LockTest.MessageEventHandler(MessageCallBack); Thread a = new Thread(new ThreadStart(test.AddNum1)); a.Name = i.ToString(); a.Start(); } }
复制代码

获得结果:

得出结论,在静态锁面前,线程依旧要排队,虽然不是一个实例,可是锁是惟一的,线程只认锁,因此线程并无并发!

继续测试(非静态的锁):

复制代码
        private void button4_Click(object sender, EventArgs e) { listBox1.Items.Clear(); for (int i = 0; i <= 2; i++) { LockTest test = new LockTest("LockTest " + i.ToString()); test.MessageEvent += new LockTest.MessageEventHandler(MessageCallBack); Thread a = new Thread(new ThreadStart(test.AddNum2)); a.Name = i.ToString(); a.Start(); } }
复制代码

获得的结果:

得出结论:非静态锁的时候,多线程并发了,一块儿在工做。

 

其实,测试的结果以前也能猜测出来,只不过,不测试下,内心老是以为没底,呵呵,测试完了,也就完全释然了!

 

窗体中,用于事件回调,显示到UI里的代码在这里:

复制代码
delegate void MessageHandler(string msg); public void MessageCallBack(object sender, MyEventArgs e) { MessageHandler handler = new MessageHandler(ShowMessage); this.Invoke(handler, new object[] { e.Message }); } public void ShowMessage(string msg) { this.listBox1.Items.Add(msg); }
复制代码
相关文章
相关标签/搜索