.NET中线程锁的使用
更新记录
本文迁移自Panda666原博客,原发布时间:2021年7月1日。
一、说明
由于经常需要在多线程代码中使用Monitor进行同步,并且需要自己去手写try/finally块。因此C#提供了一个特殊的lock关键字来简化这个流程,本质就是lock是Monitor的语法糖。
lock关键字将语句块标记为一个代码区域。确保只有一个线程位于该区域,其他线程不可以进入该区域(不会被其他线程中断)。如果其他线程要访问该区域,将一直等待,直到该区域被占用线程释放,意思就是说该区域会进行加一个互斥锁,执行完成后才会释放。
二、使用语法
lock(expression)
或者
lock(expression)
{
//互斥的代码
}
说明:
expression可以是一个类的实例(引用变量),表示保护一个类的实例。expression可以是一个静态变量,表示保护一个静态变量。提供给lock语句的参数必须为基于引用类型的对象,该对象用来定义锁的范围。严格地说,提供给lock语句的参数只是用来唯一标识由多个线程共享的资源,所以可以是任意类实例。
通常,最好避免锁定public类型或不受应用程序控制的对象实例。例如,如果该实例可以被公开访问,则lock(this)可能会有问题。因为不受控制的代码也可能会锁定该对象,这将可能导致死锁,即两个或更多个线程等待释放同一个对象。 出于同样的原因,锁定公共数据类型(相比于对象)也可能导致问题,锁定字符串 尤其危险。因为字符串被公共语言运行库(CLR)“暂留”,这意味着整个程序中 任何给定字符串都只有一个实例。最好锁定不会被暂留的私有或受保护成员。
实例:
using System.Threading;
public class PandaThreadTest
{
//锁定的对象
private readonly static object _Sync = new object();
//计数的总数
private const int _Total = 1000;
//计数的变量
private int _Count = 0;
//增加操作
public void Increment()
{
lock(_Sync)
{
//增加操作
for (int i = 0; i < _Total; i++)
{
this._Count++;
Console.WriteLine("增加操作{0}", this._Count);
}
}
}
//减少操作
public void Decrement()
{
//使用lock关键字
lock(_Sync)
{
//减少操作
for (int i = 0; i < _Total; i++)
{
_Count--;
Console.WriteLine("减少操作{0}", this._Count);
}
}
}
//模拟多线程操作
public void Test()
{
//新建线程
Thread thread1 = new Thread(this.Increment);
//开启线程
thread1.Start();
Thread thread2 = new Thread(this.Decrement);
//开启线程
thread2.Start();
//等待线程1完成
thread1.Join();
//等待线程2完成
thread2.Join();
Console.WriteLine("执行完成");
Console.WriteLine("_Count={0}",this._Count);
}
}
//进行线程的处理
PandaThreadTest pandaThreadTest = new PandaThreadTest();
//测试多线程反应
pandaThreadTest.Test();
三、如何选择lock的对象(Choosing a lock Object)
1、应确保在多线程的操作过程中不会变化比如Monitor.Enter()、Monitor.Exit()的使用中不会发生变化。否则在同步代码块的进入和退出之间将没有任何关联。
2、lock的对象不可以是值类型。如果使用值类型,运行时会报错。本质是将值类型进行装箱操作。因为Enter和Exit的装箱引用不同,different synchronization object instances,所以会导致没有任何关联出错。
四、lock本质
事实上lock语句是用Monitor类来实现的,它等效于try/finally语句块。
使用lock关键字通常比直接使用Monitor类更可取,一方面是因为lock更简洁,另一方面是因为lock确保了即使受保护的代码引发异常,也可以释放基础监视器。这是通过finally关键字来实现的,无论是否引发异常它都执行关联的代码块。
.NET中线程锁的使用的更多相关文章
- 关于Unity中协程、多线程、线程锁、www网络类的使用
协程 我们要下载一张图片,加载一个资源,这个时候一定不是一下子就加载好的,或者说我们不一定要等它下载好了才进行其他操作,如果那样的话我就就卡在了下载图片那个地方,傻住了.我们希望我们只要一启动加载的命 ...
- 并发编程---线程 ;python中各种锁
一,概念 在传统操作系统中,每个进程有一个地址空间,而且默认就有一个控制线程 线程顾名思义,就是一条流水线工作的过程,一条流水线必须属于一个车间,一个车间的工作过程是一个进程 --车间负责把资源整合到 ...
- 操作系统/应用程序、操作中的“并发”、线程和进程,python中线程和进程(GIL锁),python线程编写+锁
并发编程前言: 1.网络应用 1)爬虫 直接应用并发编程: 2)网络框架 django flask tornado 源码-并发编程 3)socketserver 源码-并发编程 2.运维领域 1)自动 ...
- JAVA 中无锁的线程安全整数 AtomicInteger介绍和使用
Java 中无锁的线程安全整数 AtomicInteger,一个提供原子操作的Integer的类.在Java语言中,++i和i++操作并不是线程安全的,在使用的时候, 不可避免的会用到synchron ...
- Java并发编程:Java中的锁和线程同步机制
锁的基础知识 锁的类型 锁从宏观上分类,只分为两种:悲观锁与乐观锁. 乐观锁 乐观锁是一种乐观思想,即认为读多写少,遇到并发写的可能性低,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新 ...
- java并发学习第五章--线程中的锁
一.公平锁与非公平锁 线程所谓的公平,就是指的是线程是否按照锁的申请顺序来获取锁,如果是遵守顺序来获取,这就是个公平锁,反之为非公平锁. 非公平锁的优点在于吞吐量大,但是由于其不是遵循申请锁的顺序来获 ...
- Python3中最常用的5种线程锁你会用吗
前言 本章节将继续围绕threading模块讲解,基本上是纯理论偏多. 对于日常开发者来讲很少会使用到本章节的内容,但是对框架作者等是必备知识,同时也是高频的面试常见问题. 官方文档 线程安全 线程安 ...
- 【Java并发系列04】线程锁synchronized和Lock和volatile和Condition
img { border: solid 1px } 一.前言 多线程怎么防止竞争资源,即防止对同一资源进行并发操作,那就是使用加锁机制.这是Java并发编程中必须要理解的一个知识点.其实使用起来还是比 ...
- 多线程中的锁系统(二)-volatile、Interlocked、ReaderWriterLockSlim
上章主要讲排他锁的直接使用方式.但实际当中全部都用锁又太浪费了,或者排他锁粒度太大了,本篇主要介绍下升级锁和原子操作. 阅读目录 volatile Interlocked ReaderWriterLo ...
随机推荐
- 时间篇之centos6下修复的ntp操作(ntpd和ntpdate两个服务区别)
系统采样,本采样和命令都是在centos6.4的系统中进行 主要比较centos7和centos6之间的差异,因为大部分都开始采用centos7但是有些老系统还采用centos6,这样我们就需要熟悉c ...
- 帝国cms修改成https后后台登陆空白的解决办法
以下方法适用帝国cms7.5版本: 7.5版本已经有了http和https自动识别,但是因为一些疑难杂症的原因,自动识别判断的不准,后台登录也是空白, 我们可以打开e/config.php查找'htt ...
- QT的MYSQL驱动库编译
QT的MYSQL驱动库编译 需要准备QT的源码Src,此次编译64位 在QTCreator中打开mysql.pro 修改两个pro 文件,下图为改好 1.mysql.pro TARGET = qsql ...
- VMware及win10虚拟机的安装及环境配置
一.安装VMware 1.1.下载VMware安装包 在此给大家一个迅雷的链接:点击下载 提取码:sp84 1.2.点击下一步 1.3.点击我接受,点击下一步 1.4.更换安装位置,点击下一步 1.5 ...
- 一篇文章带你搞懂InnoDB的索引|结合样例
关注公众号[程序员白泽],带你走进一个不一样的程序员/学生党 前言 前阵子面试的时候,在第三面问到了MySQL索引相关的知识点,并且给出了一些SQL语句分析索引的执行情况.所以今天这篇文章给大家讲讲索 ...
- 11.Flink实时项目之支付宽表
支付宽表 支付宽表的目的,最主要的原因是支付表没有到订单明细,支付金额没有细分到商品上, 没有办法统计商品级的支付状况. 所以本次宽表的核心就是要把支付表的信息与订单明细关联上. 解决方案有两个 一个 ...
- nodejs mysql pool 只能插入10条记录或者较少记录
BEGIN; 解决方案:从连接池获取到的Connection,执行完操作后,必须及时关闭! 即:connection.end(); 使用后发现console有打印出警告信息,大致意思为 end() 方 ...
- JMeter配置Oauth2.0授权接口访问
本文主要介绍如何使用JMeter配置客户端凭证(client credentials)模式下的请求 OAuth2.0介绍 OAuth 2.0 是一种授权机制,主要用来颁发令牌(token) 客户端凭证 ...
- systemd进程管理工具实战教程
关注「开源Linux」,选择"设为星标" 回复「学习」,有我为您特别筛选的学习资料~ 1. systemd介绍 systemd是目前Linux系统上主要的系统守护进程管理工具,由于 ...
- IOC创建对象的方式
1,采用无参构造创建(默认) 2,假设我们要使用有参构造创建对象 (1)下标赋值 <!--第一种 下标赋值 --><bean id="user" class=&q ...