C# lock 关键字的一些理解

C# lock 关键字的一些理解

问题1:谁是锁?

lock 这个关键字,并不是“锁”,真正的“锁”是那个被lock的Object类型的“对象”,请注意,这里为“对象”加了双引号着重强调被lock的是对象类型。

问题2:这个锁有什么用?

举个例子,多数商场厕所的蹲位都是小单间型的,也就是一次只能进去一个人,商如何确保每次只能进去一个人呢?不就是一个人进去之后顺手把门锁上么?这样你在里面干啥事,外边的人也只能等待你解放完了,才能进入。以此类推,某个 object 对象被lock之后,lock这个对象的那个线程就拥有了执行lock()后面{}的完整的独立执行权,完整且独立的执行,不可分割的执行,也就是说,{}是一块临界代码段。
看下面代码

private static object objlock = new object();
lock (objlock)
{
//这里要做一些事情
}

根据问题1的答案进行推导,objlock才是那把锁,lock 一下,当前线程就获得了紧跟在lock后面的{}的独立使用权,在此期间,其他谁都得等着拥有objlock钥匙的线程执行完之后才能使用{}里面的代码。

更专业一点的说法是:在.Net中,每个对象都有一个与之关联的锁,对象可以得到并释放它以便在任意时间只有一个线程可以访问对象实例变量和方法。同样.Net中的每一个对象都可以提供一个允许自己进入等待状态的机制。上面提到的独立使用权,就是对象的互斥锁。(关于这个说法,求证无果,只是从博客中找到的,msdn上没找到相关说法)。

问题3.为什么只能lock引用类型?

因为只有引用类型才有互斥锁,如果强行lock值类型,c#会把值装箱成引用类型,下一次再lock,还会装箱,这两次装箱实际上是装成了两个箱子,就不是用一个内存区间了,所以锁的概念就没有意义。

问题4.避免lock public类型的对象是为什么?

还是以厕所为例子吧,私有就好比,这把锁只有你能访问到,而且最好这把锁不会因为外力而有所改变,别人访问不到,这样才能保证你进去了,别人就进不去了,如果是公有的,就好比你蹲位小单间的锁不是安装在里面而是安装在外边的,别人想不想进就不是你所能控制的了,这样也不安全。

问题5.下面代码中_dic到底能不能被其他线程操作?

private static Dictionary<int, BoKwdCueItem> _dic=new Dictionary<int, BoKwdCueItem>();
static object _obj = new object();
lock (_obj)
{
///对_dic的写操作
}

个人理解上 _dic 存在被其他线程修改的可能。

private static Dictionary<int, BoKwdCueItem> _dic=new Dictionary<int, BoKwdCueItem>();
static object _obj = new object();
lock (_obj)
{
    ///对_dic的写操作
}

public void AddToDic(int data)
{
    _dic.Add(data);
}

假设A线程执行到lock(_obj)的{}的一半的时候,B线程获取的CPU的使用权,然后B线程调用了AddToDic方法,就会修改_dic的数据。

以上内容为网上搜集与个人理解,我也不保证一定对。

原文地址:https://www.cnblogs.com/feipeng8848/p/9650294.html

时间: 2024-11-05 19:36:38

C# lock 关键字的一些理解的相关文章

C#中的lock关键字有何作用

作为C#的程序员来说,在遇到线程同步的需求时最常用的就是lock关键字.但如何正确并有效地使用lock,却是能否高效地达到同步要求的关键.正因为如此,程序员需要完全理解lock究竟为程序做了什么. 所涉及的知识点 • lock的等效代码 • System.Threading.Monitor类型的作用和使用方法 分析问题 1.lock的等效代码 在.NET的多线程程序中,经常会遇到lock关键字来控制同步,比如下列代码: private object o = new object(); publi

转:C#中Monitor对象与Lock关键字的区别分析

Monitor对象1.Monitor.Enter(object)方法是获取 锁,Monitor.Exit(object)方法是释放锁,这就是Monitor最常用的两个方法,当然在使用过程中为了避免获取锁之后因为异常,致锁 无法释放,所以需要在try{} catch(){}之后的finally{}结构体中释放锁(Monitor.Exit()).2.Monitor的常用属性和方法: Enter(Object) 在指定对象上获取排他锁. Exit(Object) 释放指定对象上的排他锁. IsEnte

C#中的lock关键字

前几天与同事激烈讨论了一下,有一点收获,记录起来. 首先给出MSDN的定义: lock 关键字可以用来确保代码块完成运行,而不会被其他线程中断.这是通过在代码块运行期间为给定对象获取互斥锁来实现的. 先来看看执行过程,代码示例如下: 假设线程A先执行,线程B稍微慢一点.线程A执行到lock语句,判断obj是否已申请了互斥锁, 判断依据是逐个与已存在的锁进行object.ReferenceEquals比较(此处未加证实),如果不存 在,则申请一个新的互斥锁,这时线程A进入lock里面了. 这时假设

C++ 类的多态一(virtual关键字--构造函数深刻理解)

//virtual关键字--构造函数深刻理解 #include<iostream> using namespace std; /* C语言编译器,c++编译器全部是静态链编,就是一段一段代码的编译,不会考虑上下文 例如编译到void ProtectA(Point pin) 编译器就会认为pin就是Point类型, 而不会去联系上下文,去分析pin有没有可能是子类对象 virtual关键字会自动检测这个父类对象有没有是子类对象 */ /* virtual关键字的作用 假设父类中存在用virtua

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

本篇文章主要是对c#多线程中Lock()关键字的用法进行了详细的总结介绍,需要的朋友可以过来参考下,希望对大家有所帮助 本文介绍C# lock关键字,C#提供了一个关键字lock,它可以把一段代码定义为互斥段(critical section),互斥段在一个时刻内只允许一个线程进入执行,而其他线程必须等待. 每个线程都有自己的资源,但是代码区是共享的,即每个线程都可以执行相同的函数.这可能带来的问题就是几个线程同时执行一个函数,导致数据的混乱,产生不可预料的结果,因此我们必须避免这种情况的发生.

C# 中使用Lock关键字

 一.Lock定义     lock 关键字可以用来确保代码块完成运行,而不会被其他线程中断.它可以把一段代码定义为互斥段(critical section),互斥段在一个时刻内只允许一个线程进入执行,而其他线程必须等待.这是通过在代码块运行期间为给定对象获取互斥锁来实现的. 在多线程中,每个线程都有自己的资源,但是代码区是共享的,即每个线程都可以执行相同的函数.这可能带来的问题就是几个线程同时执行一个函数,导致数据的混乱,产生不可预料的结果,因此我们必须避免这种情况的发生. 而在.NET中

关于lock关键字

线程同步对象关键字lock,是以lock对应的object对象为准,即任意线程lock住lockObj对象之后,其他线程无论在其他任何代码段使用lock(lockObj)去进行线程同步时,都将被阻塞. 锁定的是lockObj对象,不是lock对应大括号包含的代码段. 由此可见这里的lockObj被当盾牌使,而大括号内的则是被保护的平民.  关于lock关键字

const,volatile,static,typdef,几个关键字辨析和理解

1.const类型修饰符 const它限定一个变量初始化后就不允许被改变的修饰符.使用const在一定程度上可以提高程序的安全性和可靠性.它即有预编译命令的优点也有预编译没有的优点.const修饰的变量被编译器处理只读变量(不是常量,常量是放到内存的只读区域的)放在内存中,由编译器限定不允许改变. (1)具有不可变性.  例如:const int Max=100; Max++会产生错误; (2)便于进行类型检查,使编译器对处理内容有更多了解,消除了一些隐患. 例如: void f(const i

C#中Monitor对象与Lock关键字的区别分析

这篇文章主要介绍了C#中Monitor对象与Lock关键字的区别,需要的朋友可以参考下 Monitor对象 1.Monitor.Enter(object)方法是获取 锁,Monitor.Exit(object)方法是释放锁,这就是Monitor最常用的两个方法,当然在使用过程中为了避免获取锁之后因为异常,致锁 无法释放,所以需要在try{} catch(){}之后的finally{}结构体中释放锁(Monitor.Exit()).2.Monitor的常用属性和方法: Enter(Object)