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,是我后来自己加进去的。

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

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

    /// <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种锁的区别:

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

  输出结果一模一样:

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

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

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

c#中多线程同步Lock(锁)的研究以及跨线程UI的操作 (转)的更多相关文章

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

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

  2. c#中Lock(锁)的研究以及跨线程UI的操作

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

  3. Delphi 中多线程同步的一些处理方法

    Delphi 中多线程同步的一些处理方法   当创建了多个线程,并且多个线程都要访问同一资源,,就有可能出现混乱,于是用Synchronize来控制,使同一时间只有一个线程使用那部分资源,Synchr ...

  4. python多线程threading.Lock锁用法实例

    本文实例讲述了python多线程threading.Lock锁的用法实例,分享给大家供大家参考.具体分析如下: python的锁可以独立提取出来 mutex = threading.Lock() #锁 ...

  5. [delphi]在DLL中多线程同步Synchronize卡死问题

    在dll中多线程同步调用Synchronize不可以,会出现假死卡住的现象.可通过Sendmessage实现. 转网上其他文章解释: Application.Initialize; begin     ...

  6. Java中多线程的使用(超级超级详细)线程池 7

    Java中多线程的使用(超级超级详细)线程池 7 什么是线程池? 线程池是一个容纳多个线程的容器,线程池中的线程可以重复使用,无需反复创建线程而消耗过多的资源 *使用多线程的好处: 1.降低消耗,减少 ...

  7. Java中多线程的使用(超级超级详细)线程安全原理解析 4

    Java中多线程的使用(超级超级详细)线程安全 4 什么是线程安全? 有多个线程在同时运行,这些线程可能会运行相同的代码,程序运行的每次结果和单线程运行的结果是一样的,而且其他变量的值也和预期的值一样 ...

  8. C#关于多线程及线程同步 lock锁的应用

    Form1.cs using System; using System.Collections.Generic; using System.ComponentModel; using System.D ...

  9. Java多线程---同步与锁

    一,线程的同步是为了防止多个线程访问一个数据对象时,对数据造成的破坏. 二.同步和锁定 1.锁的原理 Java中每个对象都有一个内置锁. 当程序运行到非静态的synchronized同步方法上时,自动 ...

随机推荐

  1. 金蝶K3表

    系统ID     表ID     表名     表中文名     表说明     FType     FSefDefSign0     0     t_VoucherGroup     凭证字表    ...

  2. javascript单一复制粘贴

    <div id="copy-txt">内容内容</div> <button type="submit" onclick=" ...

  3. Dubbo生产者和消费者经典案例

    一.导入依赖 <dependency> <groupId>javaee</groupId> <artifactId>javaee-api</art ...

  4. Linux下搭建iSCSI共享存储的方法 Linux-IO Target 方式 Debian9.5下实现

    iSCSI(internet SCSI)技术由IBM公司研究开发,是一个供硬件设备使用的.可以在IP协议的上层运行的SCSI指令集,这种指令集合可以实现在IP网络上运行SCSI协议,使其能够在诸如高速 ...

  5. A tow-day exam

    D1 T1l \(des:\) 给出一棵树,判断树上两条路径是否相交 \(sol:\) 判断其中一条路径的两个端点以及两端点的 \(lca\) 是否存在于另一条链上 由于这是一棵树,任一点为根后这样判 ...

  6. 如何在Processing中调用Windows应用程序

    Processing调用了exe就意味着失去了跨平台.调用的过程是,先得到当前的runtime,然后调用runtime的exec()方法,在exec()传入的是字符串参数,这个参数很重要,该有空格的地 ...

  7. 面对对大体量矢量数据ArcGIS的优化方法

    大数据量矢量数据的可视化需要解决的问题,就是如何在可接受的短时间内,能展示大数据量的矢量地图. 解决方案一:采用预先渲染的切片进行展示 切片是预先渲染的数据集,也是响应最快的展示方式.目前ArcGIS ...

  8. 本地spark报:java.lang.UnsatisfiedLinkError: org.apache.hadoop.io.nativeio.NativeIO$Windows.createFileWithMode0(Ljava/lang/String;JJJI)Ljava/io/FileDescriptor;

    我是在运行rdd.saveAsTextFile(fileName)的时候报的错,找了很多说法……最终是跑到hadoop/bin文件夹下删除了hadoop.dll后成功.之前某些说法甚至和这个解决方法自 ...

  9. 比较实用的Java工具类

    一. org.apache.commons.io.IOUtils closeQuietly:关闭一个IO流.socket.或者selector且不抛出异常,通常放在finally块 toString: ...

  10. 14.LAMP服务 Linux Apache Mysql Php和防护机制 xinetd、tcp wapper

    一.安装LAMP服务 Linux Apache Mysql Php       要求操作系统支持 php解析 apache调用php插件解析 phpmyadmin       yum install ...