一直以来对于lock关键字的用法都存有疑惑,也从网上看到很多关于他的资料包括MSDN,无奈MSDN讲述的真是让人上火。今天决定小小研究一下

一直都知道lock是锁定某一变量从而实现对某一代码段的独占执行。

但是对于lock(this)、lock(typeof(类名))、lock(字符串)、lock(公有变量) lock(私有变量) 有什么不同 却很是模糊

我假定了这样一种场景:某个时刻,只允许一个客户在打电话

定义一个客户类

代码1:(lock(this))

///定义一个Custmer类,要求某一时间,只允许一个客户在打电话
public class Custmer
{
public Custmer()
{
}
public Custmer(string name)
{
_name = name;
}
///某一时刻只允许一个客户在打电话
public void getPhone()
{
lock (this)
{ for (int i = 0; i < 10; i++)
{
Console.WriteLine(Thread.CurrentThread.Name+"正在跟客户在通话");
Thread.Sleep(1000);
} }
}
}

在主函数中调用,先实例化一个Custmer 实例

static void Main(string[] args)
{
Custmer c=new Custmer();
Thread t1 = new Thread(new ThreadStart(c.getPhone));
t1.Name = "t1";
Thread t2 = new Thread(new ThreadStart(c.getPhone));
t2.Name = "t2";
t1.Start(); t2.Start();
Console.Read(); }

可以预先分析一下结果,因为用的是lock(this),而this这时候代表的是实例c,当其中一个线程在使用的时候,另一个线程是不能使用的。也就是说,结果应该是其中一个线程先使用,另一个再使用,而不是交替使用。

运行结果1:

跟预想的结果一样,但是如果是多个客户实例呢,结果有怎样

代码2:

代码

static void Main(string[] args)
{
//这里我实例化了两个客户类
Custmer c=new Custmer();
Custmer c2 = new Custmer(); //线程1去接通c的电话
Thread t1 = new Thread(new ThreadStart(c.getPhone));
t1.Name = "t1";
//线程2去接通c2的电话
Thread t2 = new Thread(new ThreadStart(c2.getPhone));
t2.Name = "t2";
t1.Start(); t2.Start();
Console.Read(); }

再预想一下结果,对于线程t1,跟客户c接通电话,此时lock(this)中的this是当前实例c。同理,对于线程t2,this是实例c2.这样lock(this)锁定的是不同的对象,所以无法达到某一时刻,只有一个客户在电话。也就是说,两个线程会交替执行。

执行结果2:

与预想结果一样。从这里我们知道,lock(this)存在多个实例间互斥不能实现的问题,原因在于this指向的是不同的实例

另外在有的地方说lock(this)可能会造成死锁,所谓的死锁,无非就是一个线程长期锁定this不释放。 可能是lock锁定的代码段是个死循环,也可能你在一个死循环里调用lock锁定的代码段。总之是没有释放锁定对象。

Lock(typeof(类名))

我重新定义了一个sales类,用来在Customer类中锁定它

sales类

public class sales
{
public sales(string name)
{
_name = name;
}
string _name; public string Name
{
get { return _name; }
set { _name = value; }
} }

Customer类改写如下:

public class Custmer
{
public Custmer()
{
}
public Custmer(string name)
{
_name = name;
}
string _name; public string Name
{
get { return _name; }
set { _name = value; }
} public void getPhone()
{
lock (typeof(sales))//关键是这里
{ for (int i = 0; i < 10; i++)
{
Console.WriteLine(Thread.CurrentThread.Name+"正在跟客户在通话");
Thread.Sleep(1000);
} }
}
}

我们在主函数中,调用如Lock(this)的单个实例的情况,我们会发现,实现了互斥。多个实例的情况也实现了互斥。但是又有了新的问题。因为我们锁定的是类本身,所以如果有一个地方是在使用类,那么其他地方就不能使用该类,这样的限制过于苛刻。

3.Lock(字符串)

这个就更好玩了,他是实现了绝对的互斥。只要字符串内容相同,就能引起程序挂起。原因是在.NET中,字符串会被暂时存放,如果两个变量的字符串内容相同的话,.NET会把暂存的字符串对象分配给该变量。所以如果有两个地方都在使用lock(字符串)的话,它们实际锁住的是同一个对象。

那我们看一下代码和执行结果

代码:

public class Custmer
{
string flag = "ATually";//定义了一个字符串变量
public Custmer()
{
}
public Custmer(string name)
{
_name = name;
} string _name; public string Name
{
get { return _name; }
set { _name = value; }
} public void getPhone()
{
lock (flag)//关键是这里
{ for (int i = 0; i < 10; i++)
{
Console.WriteLine(Thread.CurrentThread.Name+"正在跟客户在通话");
Thread.Sleep(1000);
} }
}
}

多个实例的情况下的执行结果也实现了互斥。

对于Lock(共有变量)和Lock(私有变量)基本效果都一样,但是都会出现对于多个实例都无法实现互斥。

因此,微软推荐使用私有静态变量作为锁定的变量。但是个人觉得与锁定类和锁定字符串 没有什么不同。

以上只是个人浅见,如有错的地方,请不吝赐教,谢谢。

出处:http://www.csharpwin.com/csharpspace/12362r6119.shtml

lock关键字的用法的更多相关文章

  1. c#多线程中Lock()关键字的用法小结

    本篇文章主要是对c#多线程中Lock()关键字的用法进行了详细的总结介绍,需要的朋友可以过来参考下,希望对大家有所帮助     本文介绍C# lock关键字,C#提供了一个关键字lock,它可以把一段 ...

  2. 锁·——lock关键字详解

    作  者:刘铁猛 日  期:2005-12-25 关键字:lock 多线程 同步 小序 锁者,lock关键字也.市面上的书虽然多,但仔细介绍这个keyword的书太少了.MSDN里有,但所给的代码非常 ...

  3. C# lock 关键字的一些理解

    C# lock 关键字的一些理解 问题1:谁是锁? lock 这个关键字,并不是“锁”,真正的“锁”是那个被lock的Object类型的“对象”,请注意,这里为“对象”加了双引号着重强调被lock的是 ...

  4. lock关键字的使用

    最近在代码中,发现别人使用了lock关键字,为了理解别人写的代码,所以自己对lock关键字的使用研究了下. 微软官方解释,请百度:lock 语句(C# 参考) 微软给了个官网实例代码: class A ...

  5. [转载]C#中as和is关键字的用法

    这篇文章主要介绍了C#中as和is关键字的用法的相关资料,需要的朋友可以参考下. 原文链接:http://www.jb51.net/article/80944.htm#comments  在程序中,进 ...

  6. C++中typename关键字的用法

    我在我的 薛途的博客 上发表了新的文章,欢迎各位批评指正. C++中typename关键字的用法

  7. java中synchronized关键字的用法

    在java编程中,经常需要用到同步,而用得最多的也许是synchronized关键字了,下面看看这个关键字的用法. 因为synchronized关键字涉及到锁的概念,所以先来了解一些相关的锁知识. j ...

  8. lock关键字只不过是C#提供的语法糖

    lock关键字只不过是C#提供的语法糖, 最终使用的还是Monitor类. Monitor类的Enter方法要求传入的参数不为null, 否则会有ArgumentNullException excep ...

  9. C#的lock关键字

    using System; using System.Threading; namespace Test { class Program { //一.Lock定义 //lock 关键字可以用来确保代码 ...

随机推荐

  1. Redis "MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk"问题

    今天在程序中,jedis put数据到redis过程中,“MISCONF Redis is configured to save RDB snapshots, but is currently not ...

  2. 2、手把手教React Native实战之从React到RN

    ###React简介 RN是基于React设计,了解React有助于我们开发RN应用: React希望将功能分解化,让开发变得像搭积木一样,快速而且可维护 React主要有如下3个特点: *作为UI( ...

  3. web前端入坑第五篇:秒懂Vuejs、Angular、React原理和前端发展历史

    秒懂Vuejs.Angular.React原理和前端发展历史 2017-04-07 小北哥哥 前端你别闹 今天来说说 "前端发展历史和框架" 「前端程序发展的历史」 「 不学自知, ...

  4. SSH原理记录

    一.什么是SSH? 简单说,SSH是一种网络协议,用于计算机之间的加密登录. 如果一个用户从本地计算机,使用SSH协议登录另一台远程计算机,我们就可以认为,这种登录是安全的,即使被中途截获,密码也不会 ...

  5. cocos2d-X学习之主要类介绍:布景:CCLayer

    类继承图:  CCLayer 是CCNode的子类 ,实现了TouchEventsDelegate接口,继承了CCNode所有的特性,并且附加了一些自己的特性,它能够接收iPhone的触摸事件,也能够 ...

  6. 160720、SSM-Shiro使用详解

    前言 相比有做过企业级开发的童鞋应该都有做过权限安全之类的功能吧,最先开始我采用的是建用户表,角色表,权限表,之后在拦截器中对每一个请求进行拦截,再到数据库中进行查询看当前用户是否有该权限,这样的设计 ...

  7. 9.JavaScript简单计算器的实现

    1.难点,怎么获取标签的值,注意点,获取到的值都是string类型,还要转换 var num1 = parseInt(document.getElementById("num1") ...

  8. nodejs使用——以elasticsearch-exporter为例

    安装nodejs: yum install nodejs 运行node命令查看是否安装成功: 可以看到成功进入命令行,安装成功. node命令前面要加点,使用 .help 查看有哪些命令: 使用.ex ...

  9. [译]理解Windows消息循环

    出处:http://www.cnblogs.com/zxjay/archive/2009/06/27/1512372.html 理解消息循环和整个消息传送机制对Windows编程来说非常重要.如果对消 ...

  10. django-Query Ajax 实例 ($.ajax、$.post、$.get)

    Jquery在异步提交方面封装的很好,直接用AJAX非常麻烦,Jquery大大简化了我们的操作,不用考虑浏览器的诧异了. 推荐一篇不错的jQuery Ajax 实例文章,忘记了可以去看看,地址为:ht ...