首页 > 编程语言 >C# Lock锁对象的理解

C# Lock锁对象的理解

时间:2024-04-18 17:55:18浏览次数:26  
标签:实例 C# Lock object 对象 理解 线程 lock 字符串

我们lock的一般是对象,不是值类型和字符串。
1、为什么不能lock值类型

比如lock(1)呢?lock本质上Monitor.Enter,Monitor.Enter会使值类型装箱,每次lock的是装箱后的对象。lock 其实是类似编译器的语法糖,因此编译器直接限制住不能lock值类型。退一万步说,就算能编译器允许你lock(1),但是 object.ReferenceEquals(1,1)始终返回false(因为每次装箱后都是不同对象),也就是说每次都会判断成未申请互斥锁,这样 在同一时间,别的线程照样能够访问里面的代码,达不到同步的效果。同理lock((object)1)也不行。

2、Lock字符串

那么lock("xxx")字符串呢?MSDN上的原话是:

锁定字符串尤其危险,因为字符串被公共语言运行库 (CLR)“暂留”。 这意味着整个程序中任何给定字符串都只有一个实例,同一个对象表示了所有运行的应用程序域的所有线程中的该文本。因此,只要在应用程序进程中的任何 位置处具有相同内容的字符串上放置了锁,就将锁定应用程序中该字符串的所有实例。

3、MSDN推荐的Lock对象

通常,最好避免锁定 public 类型或锁定不受应用程序控制的对象实例。例如,如果该实例可以被公开访问,则 lock(this) 可能会有问题,因为不受控制的代码也可能会锁定该对象。这可能导致死锁,即两个或更多个线程等待释放同一对象。出于同样的原因,锁定公共数据类型(相比于 对象)也可能导致问题。

而且lock(this)只对当前对象有效,如果多个对象之间就达不到同步的效果。

而自定义类推荐用私有的只读静态对象,比如:

private static readonly object obj = new object();

为什么要设置成只读的呢?这是因为如果在lock代码段中改变obj的值,其它线程就畅通无阻了,因为互斥锁的对象变了,object.ReferenceEquals必然返回false。

 

  •  Lock 关键字锁定静态变量和非静态变量的区别

 View Code

 

单实例非静态锁,线程没有并发(加锁成功);

单实例静态锁,线程没有并发(加锁成功);

多实例非静态锁,线程并发(加锁失败);

多实例静态锁,线程没有并发(加锁成功)

标签:实例,C#,Lock,object,对象,理解,线程,lock,字符串
From: https://www.cnblogs.com/dachuang/p/18144121

相关文章

  • Pyecharts制作动态GDP柱状图
    学习使用pyecharts制作动态柱状图使用csv模块进行csv数据文件处理importcsvfrompyecharts.chartsimportBar,Timelinefrompyecharts.optionsimport*frompyecharts.globalsimportThemeTypedefdealCSVFile():"""读取处理csv数据文件:retu......
  • VKL144C/D LQFP48/SSOP48仪器仪表超低功耗/超省电LCD液晶段码驱动IC: 分贝仪、测光仪
    VKL144C/D概述:VKL144C/D是一个点阵式存储映射的LCD驱动器,可支持最大144点(36SEGx4COM)的LCD屏。单片机可通过I2C接口配置显示参数和读写显示数据,可配置4种功耗模式,也可通过关显示和关振荡器进入省电模式。其高抗干扰,低功耗的特性适用于水电气表以及工控仪表类产品。特点•工......
  • 使用c#8语法
    [C#]framework修改项目语言为C#8.0_.netframework项目如何修改c#语言-CSDN博客在项目文件中增加一条:<PropertyGroupCondition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"><PlatformTarget>AnyCPU</PlatformTarget><DebugSy......
  • Vue的class类面向对象
    一.准备工作JavaScript语言中,生成实例对象的传统方法是通过构造函数functionAnimal(name,age){this.name=name;this.age=age;}Animal.prototype.showName=function(){console.log(this.name);......
  • 10 个优化技巧,减少 Docker 镜像大小【转】
    什么是docker?Docker是一种容器引擎,可以在容器内运行一段代码。Docker镜像是在任何地方运行您的应用程序而无需担心应用程序依赖性的方式。要构建镜像,docker使用一个名为Dockerfile的文件。Dockerfile是一个包含许多指令(RUN、COPY、EXPOSE等)的文件。成功执行这些命令后,do......
  • CF1933D Turtle Tenacity: Continual Mods
    思路:此题其实很简单,不要被邪恶的出题人迷惑了双眼。此题判断有解一共有两种情况。通过题意可以知道将原数组排序后如果\(b_{1}\neb_{2}\),那么最后的结果一定\(\ne0\),这是第一种情况。第二种情况其实就是第一种情况的变形,在排序后\(b_{1}=b_{2}\)的情况下,如果\(b\)......
  • P7177 [COCI2014-2015#4] MRAVI 题解
    思路。我们知道最初添加的液体越多,那么每个蚂蚁得到的液体也就越多,又因为标签里有深搜,所以可以用DFS+二分解决(感觉说了一通废话),算是比较常规的一种解法了。在此题中我们需要魔改一下建树,需在其中添加判断此边是否为超级管道和处理通过液体的百分比这两段代码。DFS和二分的代......
  • 使用 Dockerfile 定制镜像【转】
    前言大家好,本文是对Docker自定义镜像的详细讲解,讲解了如何进行构建自己的Docker镜像以及Dockerfile的操作指令。希望对大家有所帮助~一、使用Dockerfile定制镜像1.1、Dockerfile定制镜像镜像的定制实际上就是定制每一层所添加的配置、文件。如果我们可以把每一层修改......
  • PageOffice6最简集成代码(Asp.Net)
    本文描述了PageOffice产品在普通的Asp.Net项目中如何集成调用。新建Asp.Net项目:PageOffice6-Net-Simple在您的web项目的“依赖项-包-管理NuGet程序包”中搜索到“Zhuozhengsoft.PageOfficeNet"程序后安装最新版本。拷贝pageoffice客户端安装程序到项目的bin文件夹下。客户......
  • C语言读取通达信数据
    因为无法事先知道数据的行数,只能通过计算得到,所以数组创建只能通过动态分配内存。一个解决方案是,我只想读取最后1000行,那么数组就可以直接定义大小为1000,然后把文件指针定位到倒数1000行。#include<stdio.h>#include<stdlib.h>structStock{intdate;floatopen......