C#中的lock语句是怎么回事,有什么作用?
C#中的lock语句将lock中的语句块视为临界区,让多线程访问临界区代码时,必须顺序访问。他的作用是在多线程环境下,确保临界区中的对象只被一个线程操作,防止出现对象被多次改变情况。
注意的地方有:lock对象必须是一个不可变对象,否则无法阻止另一个线程进入临界区。最好是privatestatic readonly 或者privatestatic。常见的lock(this)、lock(typeof (MyType)) 和 lock ("myLock") 都是不合理的写法。
原因:
1.lock(this),主要问题是如果类为实例化类,那么this也只是当前实例,不能起到锁定的作用,而且即使是静态类可以被锁定,那么由于尺寸问题,不如锁定不可变小对象合算。
2.lock(typeof())问题在于锁定对象类型当相于锁定类型中的静态对象部分,锁定了所有实例,速度慢;另一方面,有可能程序其他部分在访问该对象,已经替您锁定,将导致您锁定语句的挂起。原文(Here'swhy: Since there's one type object for all instances of a class, it wouldappear that locking it would provide a lock equivalent to locking a staticobject contained in your class. You would lock all instances of the class, waituntil other threads were done accessing any part of any instance, then lockaccess so you could access static members safely and without another threadinterfering.)

3.lock("")问题在于微软将内容相同的字符串视为同一个对象,如果您在此锁定了他,那么其实是锁定了同一个对象,将阻止其他地方对字符串的锁定。

lock(this)和lock(object)的比较

下面先看一个例子:创建一个窗体应用程序

首先是Oper类Oper.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;namespace TestLockObject
{class Oper{private static object obj = new object();private static Single slgTotal;public string addition(){lock (obj)<span style="color:#ff6666;">//lock(this)</span>{int i = 0;slgTotal = 0;for (i = 0; i <= 50; i++){slgTotal = slgTotal + i;Thread.Sleep(5);}return slgTotal.ToString() + " thread:" + Thread.CurrentThread.Name;}}}
}

其次是Form1.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;namespace TestLockObject
{public partial class Form1 : Form{delegate void SetTextCallback(string text);     // 设置委托public Form1(){InitializeComponent();//this.textBox.InvokeRequired = true;}/// <summary>/// 利用委托设置文本框内容/// </summary>/// <param name="text"></param>public void SetText(string text){if (this.textBox.InvokeRequired){SetTextCallback d = new SetTextCallback(SetText);this.Invoke(d, new object[] { text });}else{this.textBox.Text = this.textBox.Text + "\r\n" + text;}}private void buttonStart_Click(object sender, EventArgs e){textBox.Text = "";Thread[] thd = new Thread[500];int i = 0;for (i = 0; i < 50; i++){thd[i] = new Thread(new ParameterizedThreadStart(thdText));thd[i].Name = " Thread" + i.ToString();thd[i].IsBackground = true;thd[i].Start(i);}}/// <summary>/// 线程调用的方法/// </summary>/// <param name="obj"></param>private void thdText(object obj){Oper op = new Oper();int i = Convert.ToInt32(obj);SetText(op.addition());}}
}

分析:lock(this) 锁定的对象是当前类实例,而每个线程操作的都是oper的新实例,lock(this)只对当前实例起作用,而 slgTotal 是类的静态变量,lock(this)实际上是没在起起我们想要的结果。而lock(obj)的实例,锁定的是静态变量object,所以能够锁定每个实例。

C#设计模式-单态模式
在《Design Patterns:Elements of Resuable Object-Oriented Software》中的定义是:Ensure a class only has one instance,and provide a global point of access to。它的主要特点不是根据客户程序调用生成一个新的实例,而是控制某个类型的实例数量-唯一一个。(《设计模式-基于C#的工程化实现及扩展》,王翔)。也就是说,单态模式就是保证在整个应用程序的生命周期中,在任何时刻,被指定的类只有一个实例,并为客户程序提供一个获取该实例的全局访问点。
经典模式:

public class Singleton
{private static Singleton instance;private Singleton(){}public static Singleton GetInstance(){if(instance==null){instance=new Singleton();}return instance;}
}

解析如下:
  1)首先,该Singleton的构造函数必须是私有的,以保证客户程序不会通过new()操作产生一个实例,达到实现单态的目的;
  2)因为静态变量的生命周期跟整个应用程序的生命周期是一样的,所以可以定义一个私有的静态全局变量instance来保存该类的唯一实例;
  3)必须提供一个全局函数访问获得该实例,并且在该函数提供控制实例数量的功能,即通过if语句判断instance是否已被实例化,如果没有则可以同new()创建一个实例;否则,直接向客户返回一个实例。
  在这种经典模式下,没有考虑线程并发获取实例问题,即可能出现两个线程同时获取instance实例,且此时其为null时,就会出现两个线程分别创建了instance,违反了单态规则。因此,需对上面代码修改。
多线程下的单态模式
1、Lazy模式

public class Singleton
{private static Singleton instance;private static object _lock=new object();private Singleton(){}public static Singleton GetInstance(){if(instance==null){lock(_lock){if(instance==null){instance=new Singleton();}}}return instance;}
}

上述代码使用了双重锁方式较好地解决了多线程下的单例模式实现。先看内层的if语句块,使用这个语句块时,先进行加锁操作,保证只有一个线程可以访问该语句块,进而保证只创建了一个实例。再看外层的if语句块,这使得每个线程欲获取实例时不必每次都得加锁,因为只有实例为空时(即需要创建一个实例),才需加锁创建,若果已存在一个实例,就直接返回该实例,节省了性能开销。
2、饿汉模式
这种模式的特点是自己主动实例。
public sealed class Singleton
{
        private static readonly Singleton instance=new Singleton();
 
        private Singleton()
        {
        }
        public static Singleton GetInstance()
        {
               return instance;
        }
}
上面使用的readonly关键可以跟static一起使用,用于指定该常量是类别级的,它的初始化交由静态构造函数实现,并可以在运行时编译。在这种模式下,无需自己解决线程安全性问题,CLR会给我们解决。由此可以看到这个类被加载时,会自动实例化这个类,而不用在第一次调用GetInstance()后才实例化出唯一的单态对象。

参考文章:

(1)http://www.cnblogs.com/yuqilin/archive/2011/10/15/2213766.html

(2)http://www.cnblogs.com/xun126/archive/2011/03/09/1970807.html

浅谈对C#-lock()的理解相关推荐

  1. 浅谈 我对 技术 的理解

    文章目录 1.浅谈 我对 技术 的理解 1.1 技术 是 什么? 1.2 技术的 两个 核心 构成 要素 1.2.1 知识 层面 1.2.2 智慧 层面(思考 层面) 1.3 技术 很难?学不明白? ...

  2. 浅谈对seo概念的理解

    个人认为与微信一样,搜索引擎有固定的用户群体,有人有流量的地方,就存在商机或者利益,seo的概念就是搜索引擎优化,其目的是在搜索引擎中获得精准用户,获得流量.从更深层次方面看,利用seo做自然排名获得 ...

  3. 浅谈阿里“中台”概念的理解

    https://www.toutiao.com/a6651015208934310414/?tt_from=mobile_qq&utm_campaign=client_share&ti ...

  4. 浅谈IO及不同的理解

    IO 什么是IO? 它是指计算机与外部世界或者一个程序与计算机的其余部分的之间的接口.它对于任何计算机系统都非常关键,因而所有 I/O 的主体实际上是内置在操作系统中的.单独的程序一般是让系统为它们完 ...

  5. 浅谈我对JCS 的理解

    JCS 是Java 中缓存的一种实现,支持将数据缓存到内存和硬盘中,支持设置缓存对象的有效时长. 我认为可以这么理解JCS:客户端向服务器发出请求,服务器就先去缓存中查一下有没有客户端请求的数据,有则 ...

  6. 浅谈数据库三大范式的理解

    首先声明一下,我的这个回答是个人工作总结,不适合考试答题昂. 欢迎关注我的博客. 前言:数据库设计其实不仅仅限制于三个范式,往下其实还有很多种,但对于大多数人来说,你又不搞科研,不造飞机大炮,掌握三大 ...

  7. 浅谈对js闭包的理解

    闭包就是能够读取其他函数内部变量的函数.由于在javascript中,只有函数内部的子函数才能读取局部变量,所以闭包可以理解成"定义在一个函数内部的函数".在本质上,闭包是将函数内 ...

  8. 【Docker】Docker镜像是什么?浅谈对Docker镜像的理解

    专栏往期文章 <Docker是什么?Docker从介绍到Linux安装图文详细教程> <30条Docker常用命令图文举例总结> 本期目录 专栏往期文章 1. Docker镜像 ...

  9. 【代码注释】浅谈对于代码注释的理解

    楔子:"这里的山路十八弯,这里的水路九连环":智慧的古人就懂得,通过把山路修成九曲十八弯来战胜陡峭的高坡.看则舍近求远绕圈而行,实为拿路程换高度,为完成登顶而蓄势待发.这种螺旋上升 ...

最新文章

  1. 白话Elasticsearch58-数据建模实战_基于nested object实现博客与评论嵌套关系
  2. 异步SOCKET与同步SOCKET
  3. 四个方面快速排查工业级光纤收发器死机原因
  4. 教师计算机提升学到的知识,计算机教学质量提升措施浅谈.doc
  5. 服务器新硬盘如何挂在,Ubuntu服务器挂载新硬盘的步骤
  6. (20120731)Android中的各种对话框总结(dialog)
  7. 基于android对接百度地图搜索附近关键字列表展示并调用第三方地图应用打开导航(百度地图、高德地图)
  8. 云监控中inode使用率监控具体作用是什么
  9. spring cloud整合mybatis学习中遇到的坑
  10. 数据结构:图的深度优先遍历和广度优先遍历
  11. vue 自动播放语音
  12. 乘风领航、耀世创新——DEFI平台Lizard打造数字金融新世界
  13. php数据统计模板,PHP如何使用Echarts生成数据统计报表
  14. 测绘资质通用标准审查细则
  15. Python pypyodbc读取拆分mdb文件
  16. 世界500强企业优秀员工的十二条核心标准
  17. Windows窗体学这一篇就够了(C#控件讲解)
  18. C 使用fread读取文件
  19. MD5加密方式和MD5加密后的类型(16位和32位)
  20. 算法--运筹规划--pulp(一)

热门文章

  1. idea创建构造器快捷键
  2. H5+pdfJS的实现
  3. jdk9环境变量配置
  4. springboot启动访问页面提示404
  5. 大端模式、小端模式、高字节序、低字节序、MSB、LSB
  6. 频率学派和贝叶斯学派的参数估计
  7. ocv特性_“OCV“、“RCV"与室内质控
  8. 2023届秋招全面启动!
  9. 微型计算机gl703评测,华硕ROG Strix GL503与GL703游戏本迎来八代酷睿处理器刷新
  10. 哪个学校考研考python_考研,哪个学校最好考?