NET面试题:C#中的lock关键字有何作用
2011-03-01 08:42:04
更多.net面试题,.net电子书,.net教学视频请参考"51CTO提醒您,请勿滥发广告!"
NET面试题:C#中的lock关键字有何作用
作为C#的程序员来说,在遇到线程同步的需求时最常用的就是lock关键字。但如何正确并有效地使用lock却是能否高效地达到同步要求的关键。正因为如此,程序员需要完全理解lock究竟为程序做了什么。
所涉及的知识点
· lock的等效代码
· System.Threading.Monitor类型的作用和使用方法
分析问题
1.lock的等效代码
在.NET的多线程程序中,经常会遇到lock关键字来控制同步,比如下列代码:
private object o = new object();
public void Work()
{
lock(o)
{
//做一些需要线程同步的工作
}
}
事实上,lock这个关键字是C#为方便程序员而定义的语法,它等效于安全地使用System.Threading.Monitor类型。上面的代码就直接等效于下面的代码:
private object o = new object();
public void Work()
{
//这里很重要,是为了避免直接使用私有成员o,而导致线程不安全
Object temp = o;
System.Threading.Monitor.Enter(temp);
try
{
//做一些需要线程同步的工作
}
finally
{
System.Threading.Monitor.Exit(temp);
}
}
正如读者所看到的,真正实现了线程同步功能的,就是System.Threading.Monitor类型,lock关键字只是用来代替调用Enter、Exit方法,并且将所有的工作包含在try块内以保证其最终退出同步。
2.System.Threading.Monitor类型的作用和使用
在前文中笔者已经提到了,Monitor类型的Enter和Exit方法用来实现进入和退出对象的同步。具体来说,当Enter方法被调用时,对象的同步索引将被检查,并且.NET将负责一系列的后续工作来保证对象访问时线程的同步,而Exit方法的调用,则保证了当前线程释放该对象的同步块。
代码7-13演示了如何利用lock关键字(也就是Monitor类型)来实现线程同步,具体定义了一个包含需要同步执行方法的类型。
代码7-13 线程同步:UseLock.cs
/// <summary>
/// 演示同步锁
/// </summary>
public class Lock
{
//用来在静态方法中同步
private static Object o1 = new object();
//用来在成员方法中不同
private Object o2 = new object();
//成员变量
private static int i1 = 0;
private int i2 = 0;
/// <summary>
/// 测试静态方法的同步
/// </summary>
/// <param name="state">状态对象</param>
public static void Increment1(Object state)
{
lock (o1)
{
Console.WriteLine("i1的值为:{0}", i1.ToString());
//这里刻意制造线程并行机会
//来检查同步的功能
Thread.Sleep(200);
i1++;
Console.WriteLine("i1自增后为:{0}", i1.ToString());
}
}
/// <summary>
/// 测试成员方法的同步
/// </summary>
/// <param name="state">状态对象</param>
public void Increment2(Object state)
{
lock (o2)
{
Console.WriteLine("i2的值为:{0}", i2.ToString());
//这里刻意制造线程并行机会
//来检查同步的功能
Thread.Sleep(200);
i2++;
Console.WriteLine("i2自增后为:{0}", i2.ToString());
}
}
}
这样,在main方法中调用该类型对象的方法和其静态方法,测试其同步的效果,如代码7-14所示。
代码7-14 线程同步:UseLock.cs
/// <summary>
/// 程序入口
/// </summary>
class MainClass
{
/// <summary>
/// 测试同步效果
/// </summary>
static void Main(string[] args)
{
//开始多线程
Console.WriteLine("开始测试静态方法的同步");
for (int i = 0; i < 5; i++)
{
Thread t = new Thread(Lock.Increment1);
t.Start();
}
//这里等待线程执行结束
Thread.Sleep(5*1000);
Console.WriteLine("开始测试成员方法的同步");
Lock l = new Lock();
//开始多线程
for (int i = 0; i < 5; i++)
{
Thread t = new Thread(l.Increment2);
t.Start();
}
Console.Read();
}
}
下面是程序的执行结果:
开始测试静态方法的同步
i1的值为:0
i1自增后为:1
i1的值为:1
i1自增后为:2
i1的值为:2
i1自增后为:3
i1的值为:3
i1自增后为:4
i1的值为:4
i1自增后为:5
开始测试成员方法的同步
i2的值为:0
i2自增后为:1
i2的值为:1
i2自增后为:2
i2的值为:2
i2自增后为:3
i2的值为:3
i2自增后为:4
i2的值为:4
i2自增后为:5
可以看到,线程同步被很好地保证了。这里需要强调的是,线程同步本身违反了多线程并行运行的原则,所以读者在使用线程同步时应该尽量做到把lock加在最小的程序块上。如果一个方法有大量的代码需要线程同步,那就需要重新考虑程序的设计了,是否真的有必要进行多线程处理,毕竟线程本身的开销也是相当大的。
对静态方法的同步,一般采用静态私有的引用成员,而对成员方法的同步,一般采用私有的引用成员。读者需要注意静态和非静态成员的使用和把同步对象申明为私有,这都是保证线程同步高效并且正确的关键点。
答案
C#中的lock关键字实质是调用Monitor.Enter和Monitor.Exit两个方法的简化语法,功能上其实现了进入和退出某个对象的同步。在通常情况下,可以通过lock一个私有的引用成员变量来完成成员方法内的线程同步,而通过lock一个私有的静态引用成员变量来完成静态方法内的线程同步
转载于:https://www.cnblogs.com/mingyongcheng/archive/2011/03/27/1996716.html
NET面试题:C#中的lock关键字有何作用相关推荐
- 一起谈.NET技术,C#中的lock关键字
前几天与同事激烈讨论了一下,有一点收获,记录起来. 首先给出MSDN的定义: lock 关键字可以用来确保代码块完成运行,而不会被其他线程中断.这是通过在代码块运行期间为给定对象获取互斥锁来实现的. ...
- Haskell / GHC中的“ forall”关键字有什么作用?
本文翻译自:What does the `forall` keyword in Haskell/GHC do? I'm beginning to understand how the forall k ...
- java中的native关键字有什么作用?(java本地方法)
转自: http://zhidao.baidu.com/link?url=Xu94DBMxXz3sJyCrG7G1sCmXoHuyuYx4DMG1x7UqYL7FhfFnqF7-Z9nxIQUpntP ...
- 转:C#中Monitor对象与Lock关键字的区别分析
Monitor对象1.Monitor.Enter(object)方法是获取 锁,Monitor.Exit(object)方法是释放锁,这就是Monitor最常用的两个方法,当然在使用过程中为了避免获取 ...
- C#中Lock关键字的使用
C# 中的 Lock 语句通过隐式使用 Monitor 来提供同步功能.lock 关键字在块的开始处调用 Enter,而在块的结尾处调用 Exit. 通常,应避免锁定 public 类型,否则实例将超 ...
- 简单聊聊C#中lock关键字
为了避免多个线程同时操作同一资源,引起数据错误,通常我们会将这个资源加上锁,这样在同一时间只能有一个线程操作资源.在C#中我们使用lock关键字来锁定资源,那lock关键字是如何实现锁定的呢? 我们先 ...
- 描述C#多线程中 lock关键字
本文介绍C# lock关键字,C#提供了一个关键字lock,它可以把一段代码定义为互斥段(critical section),互斥段在一个时刻内只允许一个线程进入执行,而其他线程必须等待. 每个线程都 ...
- java volatile lock_Java并发学习笔记 -- Java中的Lock、volatile、同步关键字
Java并发 一.锁 1. 偏向锁 1. 思想背景 来源:HotSpot的作者经过研究发现,大多数情况下,锁不仅不存在多线程竞争,而且总是由同 一线程多次获得,为了让线程获得锁的代价更低而引入了偏向锁 ...
- C#中lock关键字的用法
C#提供了一个关键字lock,它可以把一段代码定义为互斥段(critical section),互斥段在一个时刻内只允许一个线程进入执行,而其他线程必须等待. 每个线程都有自己的资源,但是代码区是共享 ...
最新文章
- Entity Framework Core 批处理语句
- 11-散列3 QQ帐户的申请与登陆 (25 分)
- mysql安装(glibc版本安装5.7.22)
- mssql如何取得两位的月份和天数
- mysql中数据定义和数据控制语言_MySQL的DDL数据定义语言和DCL数据控制语言
- 5G 之战让运营商备受冷落?! | 极客头条
- 常用模拟键键值对照表(Virtual-Key Codes)
- 【渝粤题库】 陕西师范大学 202331 证券投资学 作业(专升本)
- linux下wav转换为mp3
- 【正一专栏】阿根廷和葡萄牙都进不了世界杯可能吗?
- 世界四大名柚有哪些?
- 心理学效应:阿基米德与酝酿效应
- 教你快速开发一个 狼人杀微信小程序(附源码)
- 学计算机的人会单身吗,大学里最易单身的十大专业
- 《王者荣耀游戏服务器架构演进(完整版)》读后感
- Linux下移动硬盘,创建windows,ntfs分区并挂载
- 真·骚操作!程序员埋逻辑炸弹,每隔几年就触发
- 第13周项目4 立体类族公有的抽象类
- 【k8s】Error response from daemon: Get https://192.168.22.234/v2/: dial tcp 192.168.22.234:443: connec
- MATLAB图像识别手写数字(第一篇:准备数据)
热门文章
- c# 找出目录下的所有子目录_第9期:Linux下文件系统满的处理
- html中下拉列表监听事件,ExtJS 下拉框监听事件、日期选择器监听事件、实现动态给items添加删除数据...
- learning to rank
- word中公式编辑器编号
- 2022.3.25黄花酢浆草
- NOIP2016普及组第四题——魔法阵
- android studio标题怎么改,如何在Android Studio中将应用标题更改为徽标
- 如何查看cplex的help文档_用摹客,写出更好的产品文档
- Linux系统下安装卸载jdk
- 机器学习---实战---K-近邻算法--笔记