C#中的lock语句是怎么回事,有什么作用?

C#中的lock语句将lock中的语句块视为临界区,让多线程访问临界区代码时,必须顺序访问。他的作用是在多线程环境下,确保临界区中的对象只被一个线程操作,防止出现对象被多次改变情况。

注意的地方有:lock对象必须是一个不可变对象,否则无法阻止另一个线程进入临界区。最好是private static readonly 或者private static。常见的lock (this)、lock (typeof (MyType)) 和 lock ("myLock") 都是不合理的写法。

原因:

1.lock(this),主要问题是如果类为实例化类,那么this也只是当前实例,不能起到锁定的作用,而且即使是静态类可以被锁定,那么由于尺寸问题,不如锁定不可变小对象合算。

2.lock(typeof())问题在于锁定对象类型当相于锁定类型中的静态对象部分,锁定了所有实例,速度慢;另一方面,有可能程序其他部分在访问该对象,已经替您锁定,将导致您锁定语句的挂起。原文(Here's why: Since there's one type object for all instances of a class, it would appear that locking it would provide a lock equivalent to locking a static object contained in your class. You would lock all instances of the class, wait until other threads were done accessing any part of any instance, then lock access so you could access static members safely and without another thread interfering.)

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

lock语句的一个典型应用就是单例模式。 而单例模式的一个最简单实现方式就是用静态对象方式。如下:

public class ABicycle {
private static ABicycle aBicycle = new ABicycle();
public ABicycle Instance()
{
return aBicycle;
}
}

这是实现单例模式最简单的一种方式,但是有一个缺点就是假如ABicycle类被提前调用后,aBicycle即被实例化,没法做到实例化延迟。在此情况下,利用一个关联类可以避免此问题的发生。即:

public class ABicycle {
public ABicycle Instance()
{
return ABicycleStance.Instance();
}
}
private class ABicycleStance {
internal static readonly ABicycle aBicycle = new ABicycle();
public ABicycle Instance()
{
return aBicycle;
}
}

单例模式的一个思路是利用C#的lock语句实现。 最简单实现方式为:

if(... == null){ ... = new ... } return ...;

如果这样实现,有一个问题无法回避,即无法确保只能让一个线程使对象实例化,因为有可能多个线程并发执行到此,同时实例化了对象。为此,需要引用lock语句。引用的方式也有讲究,最直接的实现方式就是:

private static readonly locker = new object(); 

//或者这样写也可以。 

//private static locker = new object(); 

lock(locker)
{
if(.. == null)
{
...
}
}

上面做法可行,但是有一个问题是每次返回时首先要对locker上锁,这样就牺牲了一些本来不必牺牲的性能,因此,可以修改为以下做法:

private static readonly locker = new object();

if(.. == null)
{
lock(locker)
{
if(... == null)
{ }
}
}

这样,对于多线程来说是安全的,而且不必每次加锁,只有在判断对象没有实例化时加锁,避免了性能上的损失。

参考资料:

http://msdn.microsoft.com/zh-cn/library/c5kehkcz.aspx

http://hi.baidu.com/benzhan/item/6304481419d6360dd1d66dff

http://bytes.com/topic/c-sharp/answers/249277-dont-lock-type-objects

c#lock语句及在单例模式中应用的更多相关文章

  1. lock语句的递归问题

    原文地址 前几天在网上闲逛,无意中看到有这么一道题及其答案,如下: 根据线程安全的相关知识,分析以下代码,当调用test方法时i>10时是否会引起死锁?并简要说明理由. ) { i--; tes ...

  2. C# lock关键词/lock语句块、线程锁

    一.lock关键词说明 1. lock 关键字将语句块标记为临界区,方法是获取给定对象的互斥锁,执行语句,然后释放该锁. 2. lock 语句块锁定,功能等同于 Monitor.Enter(obj): ...

  3. C#线程同步技术(一) lock 语句

    开篇语: 上班以后,烦恼少了,至少是没有什么好烦的了,只要负责好自己的工作就可以了,因此也有更多的时间去探索自己喜欢的程序.买回来的书已经看了一半,DEMO也敲了不少,昨晚终于在这里开BLOG,记录一 ...

  4. C# yield checked,unchecked lock语句(C#学习笔记04)

    特殊语句 yield语句 yield用于终止迭代 只能使用在返回类型必须为 IEnumerable.IEnumerable<T>.IEnumerator 或 IEnumerator< ...

  5. DCL单例模式中的缺陷及单例模式的其他实现

    DCL:Double Check Lock ,意为双重检查锁.在单例模式中懒汉式中可以使用DCL来保证程序执行的效率. 1 public class SingletonDemo { 2 private ...

  6. 一文带你.Net混合锁和lock语句

    本文主要讲解.Net基于Monitor.Enter和lock实现互斥锁 Monitor.Enter实现 相比前面的锁来说,混合锁的性能更高,任何引用类型的对象都可以做为锁对象,不需要事先创建指定类型的 ...

  7. 怎样用SQL语句查询一个数据库中的所有表?

    怎样用SQL语句查询一个数据库中的所有表?  --读取库中的所有表名 select name from sysobjects where xtype='u'--读取指定表的所有列名select nam ...

  8. SQL语句在查询分析器中可以执行,代码中不能执行

    问题:SQL语句在查询分析器中可以执行,代码中不能执行 解答:sql中包含数据库的关键字,将关键字用[]括起来,可以解决. 后记:建数据库的时候尽量避免使用关键字. 例子: sql.Format(&q ...

  9. 1、c#中可以有静态构造方法,而java中没有,例如在单例模式中c#可以直接在静态构造中实例化对象,而java不可以

    1.c#中可以有静态构造方法,而java中没有,例如在单例模式中c#可以直接在静态构造中实例化对象,而java不可以

随机推荐

  1. 我也来SplashScreen

    SplashScreen,就是平时我们说的溅射屏幕,任何一个做过客户端程序的coder应该对它都不陌生,因为它能提升用户体验,让软件看上去更美.SplashScreenForm通常进入程序时是打开,主 ...

  2. OC基础--Hello Shit

    /*  Foundation.h为主头文件, 主头文件中又拷贝了该工具箱中所有工具的头文件, 我们只需要导入主头文件就可以使用该工具箱中所有的工具, 避免了每次使用都要导入一个对应的头文件  工具箱的 ...

  3. 去掉安卓中activity的标题栏

    去掉所有Activity界面的标题栏 修改AndroidManifest.xml 在application 标签中添加android:theme="@android:style/Theme. ...

  4. Linux提供两个格式化错误信息的函数

    #include “stdio.h” Void perror(__const char *__s); 其中__s是出现错误的地方,函数向标准错误输出设备输出如下:s:错误的详细信息. Eg.perro ...

  5. node.js之windows下环境终极配置

    大家都知道现在node.js相当流行,出门在外,如果都没听说过node.js,基本上算是out了,前段时间做一个项目,用到了实时通讯功能,当时用的就是node.js来做的,我有幸有研究了一番,别的不敢 ...

  6. 为python-sproto添加map支持

    上个月太忙了,做完这个修改还没写博客,现在补一下.. 之前使用protobuf做协议打包的时候,经常会有个痛点,没法用具体数据的值作为key来索引数据.比如现在客户端上传了造兵协议,协议大概长这样: ...

  7. 最短JS判断是否为IE6(IE的写法)

    常用的 JavaScript 检测浏览器为 IE 是哪个版本的代码,包括是否是最人极端厌恶的 ie6 识别与检测.代码如下: var isIE=!!window.ActiveXObject; var ...

  8. Linux命令:nohup、df、du与/dev/null

    早上开始工作时发现服务器挂掉了,重启TongWeb时有报错: 上面的红框圈错了,第一个红框的下一行: java.io.IOException: No Space left on device 我们用d ...

  9. 一个共享内存hash

    Background 我们的多进程程序碰到一个需求:做key-value查询,然后拿获取到的value去做一些事情.这些key-value存储在很多词典文件中,数量级>10w,如果每个进程都加载 ...

  10. Windows 下的 Sublime Text 2 配置汇总, Sublime Text 3 亦可借鉴

    1)软件下载地址:http://www.sublimetext.com/2 2)安装 Package Control ,方便安装和管理插件,网络资源很多,这里附上一篇:http://www.imjef ...