c#中lock的经典示例
lock 是 C# 中的一种用于同步线程执行的机制,它帮助确保多个线程在访问共享资源时不会发生冲突或数据损坏。其作用是通过给临界区(即多线程访问共享资源的代码段)加锁,使得在同一时刻只能有一个线程进入执行该代码段。
1、lock 的工作原理
- 加锁和解锁:当一个线程进入一个 lock 块时,它会获取一个对象的锁(通常是该块代码所属对象的锁)。其他线程在该锁被释放之前无法进入同一 lock 块。当线程退出 lock 块时,它会自动释放锁。
- 防止线程冲突:lock 主要用于保护共享数据,避免多个线程同时访问或修改共享资源,造成数据不一致或程序崩溃的问题。
2、语法
lock (someObject)
{// 临界区代码:只有获得锁的线程能进入// 共享资源的操作代码
}
3、关键点
- someObject:lock 语句后面必须跟一个对象,这个对象用于在多个线程之间进行同步。通常使用类的实例对象,或是使用 this 来加锁当前对象。someObject 作为锁,通常不会使用原始类型数据或者是可变的对象。
- 自动解锁:一旦线程执行完 lock 块中的代码,锁就会自动释放,其他线程就有机会获取锁并进入临界区。
- 死锁:如果两个或多个线程相互等待对方释放锁,可能会导致死锁(即程序进入永久等待状态)。因此,设计时要注意锁的获取顺序和策略,避免这种情况。
4、lock 的实际应用
lock 经常用于以下场景:
- 操作共享数据:当多个线程需要操作同一资源时,通过 lock 来确保只有一个线程能够访问该资源,从而避免数据竞争。
- 数据库或文件访问:当多个线程需要访问数据库或文件时,需要同步这些访问操作,以防止数据损坏。
5、lock的经典示例
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;namespace Demo
{class Program{int num = 10;//设置当前总票数void Ticket(){while (true)//设置无限循环{Console.WriteLine(" " + Thread.CurrentThread.Name + " lock前");//申请locklock (this)//锁定代码块,以便线程同步{Console.WriteLine(" " + Thread.CurrentThread.Name + " lock中");//获得lockif (num > 0)//判断当前票数是否大于0{Console.WriteLine(" " + Thread.CurrentThread.Name + " Sleep(100)");Thread.Sleep(100);//使当前线程休眠100毫秒Console.WriteLine(" " + Thread.CurrentThread.Name + "----票数" + num--);//票数减1}else{Console.ReadLine();}}Console.WriteLine(" " + Thread.CurrentThread.Name + " lock后");//释放lock}}static void Main(string[] args){Program p = new Program();//创建对象,以便调用对象方法Thread tA = new Thread(new ThreadStart(p.Ticket));//分别实例化4个线程,并设置名称tA.Name = "线程A";Thread tB = new Thread(new ThreadStart(p.Ticket));tB.Name = "线程B";Thread tC = new Thread(new ThreadStart(p.Ticket));tC.Name = "线程C";Thread tD = new Thread(new ThreadStart(p.Ticket));tD.Name = "线程D";tA.Start(); //分别启动线程Console.WriteLine("tA.Start");tB.Start();Console.WriteLine("tB.Start");tC.Start();Console.WriteLine("tC.Start");tD.Start();Console.WriteLine("tD.Start");Console.ReadLine();}}
}
运行结果
tA.Start ->main中,线程A启动线程A lock前 -> 进入线程A,线程A申请lock线程A lock中 -> 线程A获得lock线程A Sleep(100) -> 线程A休眠
tB.Start ->main中,线程B启动 ->这里可以看到线程休眠程序,会返回main线程B lock前 -> 进入线程B,线程B申请lock
tC.Start ->main中,线程C启动线程C lock前 -> 进入线程C,线程C申请lock
tD.Start ->main中,线程D启动线程D lock前 -> 进入线程D,线程D申请lock线程A----票数10 -> 线程A休眠结束,线程A运行线程A lock后 -> 线程A释放lock线程A lock前 -> 线程A申请lock线程B lock中 -> 线程B获得lock线程B Sleep(100) -> 线程B休眠线程B----票数9 -> 线程B休眠结束,线程B运行 ->这里可以看到线程休眠,不会释放lock线程B lock后 -> 线程B释放lock线程B lock前 -> 线程B申请lock线程C lock中 -> 线程C获得lock线程C Sleep(100) -> 线程C休眠线程C----票数8 -> 线程C休眠结束,线程C运行线程C lock后 -> 线程C释放lock线程C lock前 -> 线程C申请lock线程D lock中线程D Sleep(100)线程D----票数7线程D lock后线程D lock前线程A lock中线程A Sleep(100)线程A----票数6线程A lock后线程A lock前线程B lock中线程B Sleep(100)线程B----票数5线程B lock后线程B lock前线程C lock中线程C Sleep(100)线程C----票数4线程C lock后线程C lock前线程D lock中线程D Sleep(100)线程D----票数3线程A lock中线程A Sleep(100)线程D lock后线程D lock前线程A----票数2线程A lock后线程A lock前线程B lock中线程B Sleep(100)线程B----票数1线程B lock后线程B lock前线程C lock中
6、 死锁的经典示例
using System;
using System.Threading;class Program
{private readonly object lock1 = new object();private readonly object lock2 = new object();public void Thread1(){lock (lock1){Console.WriteLine("Thread 1: Acquired lock1");Thread.Sleep(1000); // 模拟一些工作Console.WriteLine("Thread 1: Trying to acquire lock2");lock (lock2){Console.WriteLine("Thread 1: Acquired lock2");}}}public void Thread2(){lock (lock2){Console.WriteLine("Thread 2: Acquired lock2");Thread.Sleep(1000); // 模拟一些工作Console.WriteLine("Thread 2: Trying to acquire lock1");lock (lock1){Console.WriteLine("Thread 2: Acquired lock1");}}}static void Main(string[] args){Program p = new Program();//创建对象,以便调用对象方法// 创建两个线程Thread t1 = new Thread(p.Thread1);Thread t2 = new Thread(p.Thread2);// 启动线程t1.Start();t2.Start();// 等待线程结束t1.Join();t2.Join();}
}
运行结果
Thread 1: Acquired lock1
Thread 2: Acquired lock2
Thread 1: Trying to acquire lock2
Thread 2: Trying to acquire lock1
相关文章:
c#中lock的经典示例
lock 是 C# 中的一种用于同步线程执行的机制,它帮助确保多个线程在访问共享资源时不会发生冲突或数据损坏。其作用是通过给临界区(即多线程访问共享资源的代码段)加锁,使得在同一时刻只能有一个线程进入执行该代码段。 1、lock 的…...
python编程-集合内置函数和filter(),集合常见操作
在Python中,列表、集合、字典是三种常用的数据结构,它们各自拥有一些内置函数,用于执行各种操作。 一、列表的常用内置函数 #1、append(obj): 在列表末尾添加新的对象。list_a [1, 2, 3] list_a.append(4) print(list_a) # 输出: [1,…...
蓝桥杯Java之输入输出练习题
题目 1:多组AB(基础版) 题目描述: 输入多组数据,每组数据包含两个整数 A 和 B,计算它们的和。输入以 文件结尾(EOF) 结束。 输入格式: 每行包含两个整数 A 和 B&#x…...
FPGA的IP核接口引脚含义-快解
疑问 手册繁琐,怎样快速了解IP核各输入输出接口引脚的含义。 答疑 不慌不慌,手册确实比较详细但繁琐,如何快速知晓该部分信息,涛tao道长给你们说,简单得很,一般新入门的道友有所不知,往往后面…...
Linux的循环,bash的循环
Linux的循环,bash的循环 在 Linux 系统中,Bash 循环是最常用的循环实现方式(Bash 是 Linux 默认的 Shell),但广义上“Linux 的循环”可能涉及其他 Shell 或编程语言的循环结构。以下是 Bash 循环的详细解析及其在 Linux 环境中的…...
Qwen2-VL-2B-Instruct 模型 RK3576 板端部署过程
需要先在电脑上运行 RKLLM-Toolkit 工具,将训练好的模型转换为 RKLLM 格式的模型,然后使用 RKLLM C API 在开发板上进行推理。 在安装前先查看板端的内存容量,和自己模型占用大小比较一下,别安装编译好了不能用。 这里我就是先尝试…...
如何设计光耦电路
光耦长这样,相信小伙伴们都见过,下图是最为常用的型号PC817 怎么用?我们先看图,如下图1: Vin为输入信号,一般接MCU的GPIO口,由于这里的VCC1为3.3V,故MCU这边的供电电源不能超过3.3V…...
ADC模数转换器概念函数及应用
ADC模数转换器概念函数及应用 文章目录 ADC模数转换器概念函数及应用1.ADC简介2.逐次逼近型ADC2.1逐次逼近型ADC2.2stm32逐次逼近型2.3ADC基本结构2.4十六个通道 3.规则组的4种转换模式3.1单次转换,非扫描模式3.2连续转换,非扫描模式3.3单次转换…...
DFX(Design for eXcellence)架构设计全解析:理论、实战、案例与面试指南*
一、什么是 DFX ?为什么重要? DFX(Design for eXcellence,卓越设计)是一种面向产品全生命周期的设计理念,旨在确保产品在设计阶段就具备**良好的制造性(DFM)、可测试性(…...
【LeetCode】152、乘积最大子数组
【LeetCode】152、乘积最大子数组 文章目录 一、dp1.1 dp1.2 简化代码 二、多语言解法 一、dp 1.1 dp 从前向后遍历, 当遍历到 nums[i] 时, 有如下三种情况 能得到最大值: 只使用 nums[i], 例如 [0.1, 0.3, 0.2, 100] 则 [100] 是最大值使用 max(nums[0…i-1]) * nums[i], 例…...
Doris更新某一列数据完整教程
在Doris,要更新数据,并不像mysql等关系型数据库那样方便,可以用update set来直接更新某个列。在Doris只能进行有限的更新,官方文档如下: UPDATE - Apache Doris 1、使用Doris自带的Update功能 描述 该语句是为进行对数据进行更新的操作,UPDATE 语句目前仅支持 UNIQUE…...
《云夹:让书签管理变得轻松又高效》
在当今数字化的生活与工作场景中,我们畅游于网络的浩瀚海洋,每天都会邂逅各式各样有价值的网页内容。而如何妥善管理这些如繁星般的书签,使其能在我们需要时迅速被找到,已然成为众多网络使用者关注的焦点。云夹,作为一…...
Microsoft Fabric - 尝试一下在pipeline中发送请求给web api(获取数据和更新数据)
1.简单介绍 Microsoft Fabric中的Pipeline支持很多种activity,分成数据转换和控制流两种类型的activitly。 这边将尝试一下发送web请求的activity,要做成的pipeline大概如下图所示, 上图中有4个Activity,作用如下 Web - 从一个…...
Ruby:从宝石到编程语言的奇妙联系(中英双语)
Ruby:从宝石到编程语言的奇妙联系 在珠宝世界中,红宝石(Ruby)是一种象征热情、力量和高贵的珍贵宝石;而在编程世界中,Ruby则是一门灵活、优雅且富有创造力的编程语言。那么,这两者究竟有何联系…...
如何对java 源码进行分析, 统计出每个方法被引用的次数
使用 JavaParser 统计源码中每个方法的引用次数是一个可行且有效的方法。JavaParser 是一个用于解析 Java 源代码并生成抽象语法树(AST)的库,它提供了丰富的 API 来遍历和操作 AST。下面是一个详细的指南,说明如何使用 JavaParser…...
数据完整性与约束的分类
一、引言 为什么需要约束?为了保证数据的完整性。 (1)数据完整性 数据完整性指的是数据的精确性和可靠性。 为了保证数据的完整性,SQL对表数据进行额外的条件限制,从以下四方面考虑: ①实体完整性&…...
docker安装nacos2.x
本文为单机模式,非集群教程,埋坑 nacos2.x官方强制条件 64 bit OS,支持 Linux/Unix/Mac/Windows,推荐选用 Linux/Unix/Mac。 64 bit JDK 1.8 Maven 3.2.x 环境介绍 centos 7 maven 3.9.9 jdk 17 nacos 2.3.1 1. 拉取docker镜像 d…...
git代理设置
在 Git 中,可以通过以下命令查看当前设置的代理配置: 查看 HTTP 代理 git config --get http.proxy查看 HTTPS 代理 git config --get https.proxy查看全局代理设置 如果你设置了全局代理,可以通过以下命令查看: git config …...
python编程-内置函数bin(),bool(),abs() ,all(),any(),ascii(),max(),min() 详解
1、bin()函数用于将整数转换为其二进制字符串表示。并返回一个以0b开头的字符串,表示该整数的二进制形式。 # 十进制数转换为二进制字符串 decimal_number 42 binary_string bin(decimal_number) print(f"Decimal {decimal_number} is {binary_string} in b…...
GB/T28181 开源日记[8]:国标开发速知速会
服务端源代码 github.com/gowvp/gb28181 前端源代码 github.com/gowvp/gb28181_web 介绍 go wvp 是 Go 语言实现的开源 GB28181 解决方案,基于GB28181-2022标准实现的网络视频平台,支持 rtmp/rtsp,客户端支持网页版本和安卓 App。支持rts…...
6 maven工具的使用、maven项目中使用日志
文章目录 前言一、maven:一款管理和构建java项目的工具1 基本概念2 maven的安装与配置(1)maven的安装(2)IDEA集成Maven配置当前项目工程设置 maven全局设置 (3)创建一个maven项目 3 pom.xml文件…...
js滚动到页面最底部
setTimeout(()> { //延后执行,等页面渲染结束let container document.querySelector(.raise-flag-content); //找到当前divif (container) {container.scrollTop container.scrollHeight - (container.clientHeight - 400 );}})container.scrollTop container…...
Node.js包管理工具npm
目录 什么是 npm npm 主要功能 安装配置 npm 环境 package.json 版本范围规则 使用 npm npm 版本和帮助命令 npm 包相关命令 安装包 卸载包 升级第三方包 升级自己开发的包 查看已安装的包 清除缓存和修复 package.json 相关 运行命令脚本 全局配置 npm 包发布…...
基本数据结构--平衡二叉搜索树之红黑树示例代码
红黑树的规则。红黑树的每个节点有颜色(红或黑),满足以下性质: 每个节点是红或黑。根节点是黑的。叶子节点(NIL节点)是黑的。红节点的子节点必须是黑的。从任一节点到其所有后代叶子节点的路径包含相同数量…...
GB/T 43698-2024 《网络安全技术 软件供应链安全要求》标准解读
一、43698-2024标准图解 https://mmbiz.qpic.cn/sz_mmbiz_png/rwcfRwCticvgeBPR8TWIPywUP8nGp4IMFwwrxAHMZ9Enfp3wibNxnfichT5zs7rh2FxTZWMxz0je9TZSqQ0lNZ7lQ/640?wx_fmtpng&fromappmsg 标准在线预览: 国家标准|GB/T 43698-2024 相关标准: &a…...
Python内置函数map(), list(), len(), iter(), hex(), hash()的详细解析,包括功能、语法、示例及注意事项
1. map(function, iterable, ...) 功能:对可迭代对象中的每个元素应用指定函数,返回一个迭代器。 参数: function:要执行的函数(可以是lambda表达式)。 iterable:一个或多个可迭代对象&#x…...
CF 278A.Circle Line
题目分析 输入n个数据作为路径,求从a到b的最短距离,需要将其相成一个圆圈,既可以从小往大走又可以从大往小走 思路分析 依然将数据存为数组,通过下标进行操作,既然说了有两种方式那就计算两种方式哪个更快就输出谁 代…...
DeepSeek模型构建与训练
在完成数据预处理之后,下一步就是构建和训练深度学习模型。DeepSeek提供了简洁而强大的API,使得模型构建和训练变得非常直观。无论是简单的全连接网络,还是复杂的卷积神经网络(CNN)或循环神经网络(RNN),DeepSeek都能轻松应对。本文将带你一步步构建一个深度学习模型,并…...
本地部署deepseek简单教程
部署deepseek,首先需要知道deepseek官网地址:DeepSeek 第一步:Ollama 去ollama下载对应的版本,我的电脑是window 在这里可以看到关于deepseek相关 第二步,下载完ollama无脑下一步就可以 这样属于安装成功 第三步&…...
3.1 可视化算子编程语言
HuggingFists的VO编程语言与常见的其它编程语言有一定的区别。其语言由两种不同的语法特征构成。一部分以可视化算子作为语法基础(简称:VO-O),辅助使用者可视化的完成数据处理/分析流程的编写;一部分采用表达式语法(简称:VO-E)&am…...
