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

本文只针对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);
        }
时间: 2024-12-12 06:45:11

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

MFC中CAsyncSocket及其派生类对象跨线程使用方法

存在的现象 在MFC中用多线程方法开发WinSocket通讯程序时,如果你的的是API方式,自然没有以下说的问题.但如果当你使用CAsyncSocket及其派生类(CSocket或是你自己的写的)来开发的话,会发现在不同线程中使用CAsyncSocket及其派生类对象时,会出现程序崩溃.这里所说的跨线程,是指该对象在一个线程中调用Create/Close/Attach/Detach函数,然后在另外一个线程中调用其他成员函数如Receive/ReceiveFrom/Send/SendTo等.下面是

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

ReentrantLock在进行实例化时,可以通过构造函数的参数选择是否使用公平锁FairSync或者非公平锁NonfairSync,两者的区别比较简单,如果是公平锁则新来的线程会先检测同步队列中是否有等待的线程,如果有,则追加到同步队列尾,锁竞争过程强调的是有序进行,当然代价比较明显,线程切换会造成额外消耗:而对于非公平锁,新来的线程会直接参与竞争,比如一个线程刚刚释放锁但CPU时间片还没结束,如果再次争夺锁,那明显会更容易成功,也就是以无序争夺锁来降低线程切换从而提高吞吐量. 这里以Nonf

WINFORM中加入WPF控件并绑定数据源实现跨线程自动更新

1. WINFORM中添加两个ElementHost,一个放WPF的Button,一个放WPF的TextBox.其中TextBox与数据源绑定,实现跨线程也可以自动更新,而不会出现WINFORM的TextBox控件与数据源绑定后,存在子线程中更新数据源报错(跨线程更新控件)的情况. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System

【转载】Java中的锁机制 synchronized &amp; Lock

参考文章: http://blog.csdn.net/chen77716/article/details/6618779 目前在Java中存在两种锁机制:synchronized和Lock,Lock接口及其实现类是JDK5增加的内容,其作者是大名鼎鼎的并发专家Doug Lea.本文并不比较synchronized与Lock孰优孰劣,只是介绍二者的实现原理. 数据同步需要依赖锁,那锁的同步又依赖谁?synchronized给出的答案是在软件层面依赖JVM,而Lock给出的方案是在硬件层面依赖特殊的

java学习第22天(关于java中的锁LOCK及多线程的面试题)

在JDK5后,java提供一种更加方便的安全机制,不使用synchronized,针对线程的锁定操作和释放操作使用Lock锁.更加清晰明了.举例: Lock lock=new ReentrantLock(); lock.lock 需要加锁的代码 lock.unlock  为什么说lock更为安全呢?因为synchronized可能会造成死锁现象,具体关于死锁现象可以参考操作系统,就不再多说. 总结下在线程中的主要几个问题 首先是 多线程有几种实现方式 应该上是有三种,第一种继承Thread类,第

c#语言-多线程中的锁系统

介绍 平常在多线程开发中,总避免不了线程同步.这次就对net多线程中的锁系统做个简单描述. 目录 一:lock.Monitor 1:基础. 2: 作用域. 3:字符串锁. 二: mutex 三:Semaphore 四:总结 一:lock.Monitor 1:基础 Lock是Monitor语法糖简化写法.Lock在IL会生成Monitor. //======Example 1===== string obj = "helloworld"; lock (obj) { Console.Wri

Objective-C中的锁及应用-13- 多线程

Objective-C中的锁及应用 在多线程编程中,锁是非常重要的工具,而Objective-C提供了好几种不同类型的锁,下面就来看一下这些锁都是怎么用的. 0. POSIX Mutex Lock Mutex lock也就是互斥锁,是Unix/Linux平台上提供的一套同步机制.互斥锁提供了三个函数,从函数名就可以知道他们的作用: int pthread_mutex_lock(pthread_mutex_t *mutex); int pthread_mutex_trylock(pthread_m

转: 【Java并发编程】之二十:并发新特性—Lock锁和条件变量(含代码)

简单使用Lock锁 Java5中引入了新的锁机制--Java.util.concurrent.locks中的显式的互斥锁:Lock接口,它提供了比synchronized更加广泛的锁定操作.Lock接口有3个实现它的类:ReentrantLock.ReetrantReadWriteLock.ReadLock和ReetrantReadWriteLock.WriteLock,即重入锁.读锁和写锁.lock必须被显式地创建.锁定和释放,为了可以使用更多的功能,一般用ReentrantLock为其实例化

c#语言-多线程中的锁系统(一)

介绍 平常在多线程开发中,总避免不了线程同步.本篇就对net多线程中的锁系统做个简单描述. 目录 一:lock.Monitor 1:基础. 2: 作用域. 3:字符串锁. 4:monitor使用 二:mutex 三:Semaphore 四:总结 一:lock.Monitor 1:基础 Lock是Monitor语法糖简化写法.Lock在IL会生成Monitor. //======Example 1===== string obj = "helloworld"; lock (obj) {