本文只针对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种锁的区别:
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的操作 (转)

    https://www.cnblogs.com/tommyheng/p/4104552.html 本文只针对C#中,多线程同步所用到的锁(lock)作为研究对象.由于想更直观的显示结果,所以,在做de ...

  3. [WinForm]WinForm跨线程UI操作常用控件类大全

    前言 在C#开发的WinForm窗体程序开发的时候,经常会使用多线程处理一些比较耗时之类的操作.不过会有一个问题:就是涉及到跨线程操作UI元素. 相信才开始接触的人一定会遇上这个问题. 为了解决这个问 ...

  4. 通过ReentrantLock简单了解下并发包中的锁

    ReentrantLock在进行实例化时,可以通过构造函数的参数选择是否使用公平锁FairSync或者非公平锁NonfairSync,两者的区别比较简单,如果是公平锁则新来的线程会先检测同步队列中是否 ...

  5. 在.Net中进行跨线程的控件操作(上篇:Control.Invoke)

    本文的重点在于介绍如何在多线程编程中,从非UI线程上访问界面中的控件.有过多线程编程经验的人都知道,当我们在非UI线程上试图给一个界面中的控件赋值的时候,比如说label的Text属性,系统会抛出一个 ...

  6. WPF 中那些可跨线程访问的 DispatcherObject(WPF Free Threaded Dispatcher Object)

    原文 WPF 中那些可跨线程访问的 DispatcherObject(WPF Free Threaded Dispatcher Object) 众所周知的,WPF 中多数对象都继承自 Dispatch ...

  7. 『动善时』JMeter基础 — 38、JMeter中实现跨线程组关联

    目录 1.JMeter中实现跨线程组关联说明 (1)JMeter中实现跨线程组关联步骤 (2)测试计划内包含的元件 2.用户登陆请求的相关操作 (1)进行登陆操作获取Cookie信息 (2)把Cook ...

  8. Winfrom 如何安全简单的跨线程更新控件

    来源:http://www.cnblogs.com/rainbowzc/archive/2010/09/29/1838788.html 由于多线程可能导致对控件访问的不一致,导致出现问题.C#中默认是 ...

  9. MySql InnoDB中的锁研究

    # MySql InnoDB中的锁研究 ## 1.InnoDB中有哪些锁### 1. 共享和排他(独占)锁(Shared and Exclusive Locks) InnoDB实现标准的行级锁定,其中 ...

随机推荐

  1. (转)linux下mysql的安装过程

    最近在linux安装了mysql,根据网上收集的资料和个人的操作过程,大概做了个整理,以便以后进行参考回顾. 1.下载mysql-5.1.36.tar.gz,并且解压. tar -xzvf mysql ...

  2. 如何一行jquery代码写出tab标签页(链式操作)

    啦啦!今天又学了一招,js写几十行的tab标签页jquery写一行就行啦,用到了链式操作!以下是代码: <!DOCTYPE html> <html lang="en&quo ...

  3. Java创建线程的第二种方式:实现runable接口

    /*需求:简单的卖票程序多个窗口买票 创建线程的第二种方式:实现runable接口 *//*步骤1.定义类实现Runable接口2.覆盖Runable接口中的run方法    将线程要运行的代码存放在 ...

  4. nodejs的调试

    js的调试始终是一个比较麻烦也是比较困难的事情,从最原始的alert调试,到火狐的firebug工具,在到后来各个浏览器厂商的调试工具.调试工具的发展历程,也可以看出由JS构建的业务和技术逻辑越来越复 ...

  5. Kali-Linux之开启ssh服务

    需求:通过putty软件ssh到Kali-Linux系统 问题:默认情况下,Kali系统的ssh服务并没有开启 操作方法: 1.编辑sshd_config文件 root@kali:~# vi /etc ...

  6. web api写api接口时返回

    web api写api接口时默认返回的是把你的对象序列化后以XML形式返回,那么怎样才能让其返回为json呢,下面就介绍两种方法: 方法一:(改配置法) 找到Global.asax文件,在Applic ...

  7. 浏览器检测(BrowserDetect.js)

    浏览器检测是在工作中经常用到的,如果只是简单判断当前是什么浏览器的话可以通过window.navigator.useragent这样的js来直接判断就可以了! 但是针对浏览器版本要求比较高的时候,如果 ...

  8. 虚拟机添加磁盘LVM分区

    参考博客:http://kimjinlsgd.blog.51cto.com/1918030/932210 一.查看磁盘情况 新添加一块磁盘. [root@VMhost /]# fdisk -l Dis ...

  9. Oracle本地,远程,分布式登录

    identify认证,确定; identity同一性,个性; 本地连接 sqlplus scott/tiger@localhost:1521/orcl 这句话就等于sqlplus scott/tige ...

  10. ASP.NET异常:找到多个具有相同ID"xxx"的控件。FindControl要求控件具有唯一的ID

    出错场景是这样使用的: 1.FindControl遍历Page.Form.Controls,将其放到一个List里. 2.Page.Form.Controls.Clear(),清空所有控件 3.往Pa ...