C# lock

news2025/5/20 2:05:30

在C#中,lock关键字用于确保当一个线程位于给定实例的代码块中时,其他线程无法访问同一实例的该代码块。这是一种简单的同步机制,用来防止多个线程同时访问共享资源或执行需要独占访问的代码段(临界区),从而避免竞态条件和数据不一致问题。

使用方式

lock语句的基本语法如下:

lock (expression)
{
    // 需要同步的代码块
}

这里的expression必须是一个可以被引用的对象,通常是一个私有的、专门用于锁定目的的对象。lock实际上是对Monitor.EnterMonitor.Exit方法的封装,并且它保证了即使在发生异常的情况下也会正确释放锁。

工作原理

  • 当一个线程到达lock语句时,它会尝试获取由expression指定对象的锁。
  • 如果锁是可用的(即没有其他线程持有该锁),则该线程获得锁并进入临界区执行代码。
  • 如果锁已经被另一个线程持有,则当前线程将被阻塞,直到锁被释放。
  • 一旦线程完成临界区内的操作,lock确保调用Monitor.Exit来释放锁,这样等待中的其他线程就可以继续执行。

注意事项

  1. 唯一性:建议为每个需要保护的共享资源使用独立的锁对象。不要使用公共对象如this或类型本身(typeof(TypeName))作为锁对象,以避免不必要的锁竞争。

  2. 不可变性:作为锁的对象最好是不可变的(immutable),因为如果锁对象的状态可以改变,可能会导致不确定的行为。

  3. 引用类型:只能对引用类型的对象加锁。值类型不能用于lock,因为每次装箱都会创建一个新的对象,这将破坏锁定的目的。

  4. 性能考虑:虽然lock是实现简单同步的有效手段,但过度使用或不当使用可能导致性能瓶颈甚至死锁。尽量减少锁的作用范围,并考虑使用更高级的并发工具如ReaderWriterLockSlimConcurrentDictionary等。

  5. 避免死锁:设计多线程程序时要注意避免死锁,即两个或更多的线程互相等待对方释放锁的情况。一种预防措施是保持一致的锁获取顺序。

示例代码

下面是一个简单的例子,演示如何使用lock来保护共享资源:

private readonly object lockObject = new object();
private int counter = 0;

public void IncrementCounter()
{
    lock (lockObject)
    {
        counter++;
    }
}

在这个例子中,lockObject是用来保护counter变量的锁。通过这种方式,我们可以确保在同一时间只有一个线程能够修改counter的值,从而避免竞态条件。

为什么不能lock值类型

在C#中,lock语句要求其参数必须是一个引用类型的对象,而不能是值类型。这是因为lock机制依赖于对象的引用标识来实现同步控制,具体来说,lock实际上是对指定对象进行加锁操作,确保同一时间只有一个线程能够执行被锁定保护的代码块。

当你尝试对一个值类型使用lock时,会发生以下情况:

  1. 装箱(Boxing):由于lock只能接受引用类型作为参数,因此如果传递了一个值类型,编译器会自动对该值类型进行装箱操作,将其转换为一个引用类型(即Object类型的一个实例)。这意味着每次执行lock时都会创建一个新的对象。

  2. 失去锁定的意义:由于每次装箱都会创建一个新的对象,即使你多次对同一个值类型变量使用lock,它们实际上是在不同的对象上加锁。因此,这不会产生预期的同步效果,因为不同线程可能会同时获取到“锁”,导致竞态条件的发生。

例如,下面的代码试图对一个整型变量进行锁定,但实际上并不会按预期工作:

int number = 0;
lock (number) // 编译错误:无法对值类型使用 lock 语句
{
    // Do something...
}

正确的做法是使用一个专门的引用类型对象作为锁对象。通常,我们会定义一个私有的、只读的对象用于锁定目的,以避免意外的锁竞争和确保锁定的有效性。例如:

private readonly object lockObject = new object();
int number = 0;

lock (lockObject)
{
    number++;
}

这样做的好处是可以确保所有希望同步访问共享资源的线程都在同一个对象上等待锁,从而达到预期的同步效果。总之,为了避免上述问题并正确地实现同步逻辑,应始终使用引用类型的对象作为lock的目标。

参考链接

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2379658.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【拥抱AI】Deer-Flow字节跳动开源的多智能体深度研究框架

最近发现一款可以对标甚至可能超越GPT-Researcher的AI深度研究应用,Deer-Flow(Deep Exploration and Efficient Research Flow)作为字节跳动近期开源的重量级项目,正以其模块化、灵活性和人机协同能力引发广泛关注。该项目基于 La…

前端获取用户的公网 IP 地址

可以使用免费的免费的公共服务网站 一:https://www.ipify.org/ 获取 JSON 格式的 IP 地址 // 旧地址不好使 // https://api.ipify.org/?formatjson // 新地址 https://api64.ipify.org/?formatjson 二:https://ipinfo.io/ https://ipinfo.io/ 三&a…

云电竞服务器 工作原理

云电竞服务器工作原理详解 一、核心架构原理 虚拟化资源池‌ 通过 ‌KVM/VMware‌ 等虚拟化技术将物理服务器(含NVIDIA GPU集群)抽象为可动态分配的算力资源池,每个用户独享独立虚拟机实例,实现硬件资源的按需分配与隔离运行。 …

【数据结构】线性表--队列

【数据结构】线性表--队列 一.什么是队列二.队列的实现1.队列结构定义:2.队列初始化函数:3.队列销毁函数:4.入队列函数(尾插):5.出队列函数(头删):6.取队头元素&#xff…

[Vue3]语法变动

Vue3的语法相对比Vue2有不少改变,这篇讲一下基础语法在Vue3里的形式。 创建Vue对象 在脚手架项目中,index.html等资源不再编写代码,只作为一个容器。所有的页面代码都在.vue相关文件中进行编写,由main.js引入各个.vue文件渲染出页…

Ubuntu服务器开启SNMP服务 监控系统配置指南 -优雅草星云智控简易化操作

Ubuntu服务器开启SNMP服务 & 监控系统配置指南 -优雅草星云智控简易化操作 一、Ubuntu服务器开启SNMP服务 步骤1:安装SNMP服务 sudo apt update sudo apt install snmp snmpd snmp-mibs-downloader -y 步骤2:配置SNMP(编辑配置文件&am…

linux本地部署ollama+deepseek过程

1.Tags ollama/ollama GitHub 选择一个版本下载,我下的是0.5.12 2.tar解压该文件 3.尝试启动ollama ollama serve 4.查看ollama的版本 ollama -v 5.创建一个系统用户 ollama,不允许登录 shell,拥有一个主目录,并且用…

从零开始实现大语言模型(十五):并行计算与分布式机器学习

1. 前言 并行计算与分布式机器学习是一种使用多机多卡加速大规模深度神经网络训练过程,以减少训练时间的方法。在工业界的训练大语言模型实践中,通常会使用并行计算与分布式机器学习方法来减少训练大语言模型所需的钟表时间。 本文介绍PyTorch中的一种…

OpenCV进阶操作:指纹验证、识别

文章目录 前言一、指纹验证1、什么是指纹验证2、流程步骤 二、使用步骤(案例)三、指纹识别(案例)1、这是我们要识别的指纹库2、这是待识别的指纹图3、代码4、结果 总结 前言 指纹识别作为生物识别领域的核心技术之一,…

网络安全-等级保护(等保) 2-5 GB/T 25070—2019《信息安全技术 网络安全等级保护安全设计技术要求》-2019-05-10发布【现行】

################################################################################ GB/T 22239-2019 《信息安全技术 网络安全等级保护基础要求》包含安全物理环境、安全通信网络、安全区域边界、安全计算环境、安全管理中心、安全管理制度、安全管理机构、安全管理人员、安…

3D生成新突破:阶跃星辰Step1X-3D开源,可控性大幅提升

Step1X-3D 是由 StepFun 联合 LightIllusions 推出的新一代 高精度、高可控性 3D资产生成框架。基于严格的 数据清洗与标准化流程,我们从 500万 3D资产 中筛选出 200万高质量数据,构建了 标准化的几何与纹理属性数据集,为3D生成提供更可靠的训…

MySQL数据类型之VARCHAR和CHAR使用详解

在设计数据库字段时,字符串类型算是最常见的数据类型之一了,这篇文章带大家深入探讨一下MySQL数据库中VARCHAR和CHAR数据类型的基本特性,以及它们之间的区别。 VARCHAR类型 VARCHAR(Variable Character,可变长度字符…

《Docker 入门与进阶:架构剖析、隔离原理及安装实操》

1 docker 简介 1.1 Docker 的优点 Docker 是一款开放平台,用于应用程序的开发、交付与运行,能将应用和基础架构分离,实现软件快速交付 ,还能以统一方式管理应用和基础架构,缩短代码从编写到上线的时间。其核心优势如…

基于Akamai云计算平台的OTT媒体点播转码解决方案

点播视频(VOD)流媒体服务依赖于视频流的转码来高效分发内容。在转码工作流程中,视频被转换为适合观看设备、网络条件和性能限制的格式。视频转码是计算密集型过程,因此最大化可用硬件上可转码的视频流数量是首要考虑因素。不同基础…

【MySQL】02.数据库基础

1. 数据库的引入 之前存储数据用文件就可以了,为什么还要弄个数据库? 文件存储存在安全性问题,文件不利于数据查询和管理,文件不利于存储海量数据,文件在程序中控制不方便。而为了解决上述问题,专家们设计出更加利于…

选错方向太致命,华为HCIE数通和云计算到底怎么选?

现在搞HCIE的兄弟越来越多了,但“数通和云计算,到底考哪个?”这问题,依旧让不少人头疼。 一个是华为认证的老牌王牌专业——HCIE数通,稳、系统、岗位多; 一个是新趋势方向,贴合云原生、数字化…

经典启发算法【早期/启发式/HC爬山/SA模拟退火/TS禁忌搜/IA免疫 思想流程举例全】

文章目录 一、早期算法二、启发式算法三、爬山法HC3.1 基本思路3.2 伪代码 四、模拟退火SA4.1 算法思想4.2 基本流程4.3 再究原理4.3.1 Metropolis准则4.3.2 再理解 4.4 小Tips4.5 应用举例4.5.1 背包问题:分析:求解: 4.5.2 TSP问题&#xff…

IntraWeb 16.0.2 + Bootstrap 4 居中布局实战(附源码+效果图)

前言 最近在优化一个 IntraWeb 16.0.2 项目时,发现默认布局方式不够灵活,尤其是在不同屏幕尺寸下对齐效果不佳。于是,我决定引入 Bootstrap 4 来实现 完美居中布局,并成功落地!今天就把完整的 源代码 实际效果图 分享…

【Java ee初阶】jvm(3)

一、双亲委派机制(类加载机制中,最经常考到的问题) 类加载的第一个环节中,根据类的全限定类名(包名类名)找到对应的.class文件的过程。 JVM中进行类加载的操作,需要以来内部的模块“类加载器”…

23种设计模式考试趋势分析之——适配器(Adapter)设计模式——求三连

文章目录 一、考点分值占比与趋势分析二、真题考点深入挖掘三、"wwwh"简述四、真题演练与解析五、极简备考笔记 适配器模式核心要点六、考点记忆顺口溜七、多角度解答 一、考点分值占比与趋势分析 由于知识库提供的真题年份信息不完整,我们仅能对现有数据…