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

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

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

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

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

备注:原文并没有加readonly,是我后来自己加进去的。

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

然后我写了一段代码进行测试,测试类代码如下:

fz.gif

/// ///跨线程操作UI的时候传递的参数,本文为了显示消息,所以简单的封装了一个 /// public classMyEventArgs : EventArgs { public readonly string Message = string.Empty; public MyEventArgs(stringmsg) { this.Message =msg; } } /// ///测试类,用于测试2种锁的区别 /// public classLockTest { //2个锁 private static readonly object Locker1 = new object(); private readonly object Locker2 = new object(); /// ///跨线程操作UI的委托和事件 /// public delegate void MessageEventHandler(objectsender, MyEventArgs e); public eventMessageEventHandler MessageEvent; public voidOnMessage(MyEventArgs e) { if (this.MessageEvent != null) MessageEvent(this, e); } //要锁的变量,通过它可以看出2种锁在不同情况下的效果 private int num = 0; //实例名字 private readonly stringName; public LockTest(stringname) { Name =name; } //第一种锁执行的方法 public voidAddNum1() { lock(Locker1) { num = 0; ShowMessage(); } } //第二种锁执行的方法 public voidAddNum2() { lock(Locker2) { num = 0; ShowMessage(); } } //锁内的一些操作,并通过事件,把关键的消息显示到主线程中的UI里 private voidShowMessage() { 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(newMyEventArgs(msg)); Thread.Sleep(100); } msg = string.Format("======线程 [{0}]执行完毕======", Thread.CurrentThread.Name); OnMessage(newMyEventArgs(msg)); } }

fz.gif

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

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

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

}

}

输出结果一模一样:

2677288368029ea8c7179466eeff69a0.png

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

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

fz.gif

private void button3_Click(objectsender, EventArgs e) { listBox1.Items.Clear(); for (int i = 0; i <= 2; i++) { LockTest test = new LockTest("LockTest " +i.ToString()); test.MessageEvent += newLockTest.MessageEventHandler(MessageCallBack); Thread a = new Thread(newThreadStart(test.AddNum1)); a.Name =i.ToString(); a.Start(); } }

fz.gif

得到结果:

44b7f692ba5d2184ea6c56281562eb99.png

得出结论,在静态锁面前,线程依旧要排队,虽然不是一个实例,但是锁是唯一的,线程只认锁,所以线程并没有并发!

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

fz.gif

private void button4_Click(objectsender, EventArgs e) { listBox1.Items.Clear(); for (int i = 0; i <= 2; i++) { LockTest test = new LockTest("LockTest " +i.ToString()); test.MessageEvent += newLockTest.MessageEventHandler(MessageCallBack); Thread a = new Thread(newThreadStart(test.AddNum2)); a.Name =i.ToString(); a.Start(); } }

fz.gif

得到的结果:

cbb8edff6456a7eef6133a446def0074.png

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

其实,测试的结果之前也能猜想出来,只不过,不测试下,心里总是觉得没底,呵呵,测试完了,也就彻底释然了!

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

fz.gif

delegate void MessageHandler(stringmsg); public void MessageCallBack(objectsender, MyEventArgs e) { MessageHandler handler = newMessageHandler(ShowMessage); this.Invoke(handler, new object[] { e.Message }); } public void ShowMessage(stringmsg) { this.listBox1.Items.Add(msg); }

fz.gif

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值