首页 > 其他分享 >string类型可以作为lock的锁对象吗

string类型可以作为lock的锁对象吗

时间:2023-06-23 17:13:49浏览次数:41  
标签:string 对象 lock 类型 线程 引用 字符串

lock 关键字介绍

lock 关键字是用于在多线程编程中实现同步和互斥访问的关键字。它的作用是确保共享资源在任意时刻只能被一个线程访问,从而避免出现竞态条件(race condition)和数据不一致的问题。

当多个线程同时访问共享资源时,如果没有合适的同步机制,可能会导致数据损坏、结果的不确定性或其他不可预测的行为。

使用 lock 关键字可以解决这个问题。当一个线程进入 .NET lock 块时,它会获取到指定的锁对象,并且其他线程将被阻塞,直到该线程释放锁对象。

private static object lockObject = new object();

//在进入 lock 块之前,线程会尝试获取 lockObject 的锁,如果锁可用,则进入代码块执行操作;如果锁不可用(已被其他线程持有),则线程将被阻塞,直到锁被释放。
lock (lockObject)
{
}

lock 语句的正文中引发异常,也会释放 lock

lock (x)
{
    // Your code...
}

//等同于
object __lockObj = x;
bool __lockWasTaken = false;
try
{
    System.Threading.Monitor.Enter(__lockObj, ref __lockWasTaken);
    // Your code...
}
finally
{
    if (__lockWasTaken) System.Threading.Monitor.Exit(__lockObj);
}

由于该代码使用 try-finally 语句,因此即使在 lock 语句的正文中引发异常,也会释放 lock。


lock 关键字的锁对象必须是引用类型,而不能是值类型。

image

在 lock 语句的正文中不能使用 await 表达式

image

lock 锁定对象实例,通常使用引用对象

在 C# 中,引用类型包括类、接口、委托等。引用类型具有一个重要的特性,即它们在内存中具有唯一的地址。因此,能够使用引用类型作为锁对象,让多个线程通过共享同一个引用来实现同步。

当多个线程尝试进入 lock 代码块时,它们需要获取锁对象的控制权。如果使用值类型作为锁对象,每个线程都会创建并持有自己的锁对象实例,导致无法达到互斥的目的。因为值类型是每个实例独立存在的,它们在内存中具有不同的地址,这样就无法确保多个线程之间共享同一个锁对象。

使用引用类型作为锁对象可以解决这个问题。多个线程可以通过使用相同的引用对象来获取锁的控制权,并且只有一个线程能够成功获取锁,其他线程将被阻塞。这样,就实现了所谓的互斥访问,确保了线程安全。

string类型也是引用类型,为什么不推荐

在 .NET Framework 中,由于字符串类型的特殊性,编译器对字符串进行了一种优化,即字符串的常量值会被缓存并重用。这意味着多个字符串变量引用相同的字符串常量时,它们实际上引用的是同一个内存位置,或者说字符串常量是“暂留”的。

由于字符串常量的“暂留”特性,如果将字符串作为锁对象,可能会导致意外的行为和不正确的同步。因为其他部分的代码也可能引用相同的字符串常量,并且在不同的上下文中使用该字符串作为锁对象,这可能导致无法预测的竞争条件。

标签:string,对象,lock,类型,线程,引用,字符串
From: https://www.cnblogs.com/lgxlsm/p/17499346.html

相关文章

  • Kotlin 语法糖(对象不为空返回自身,为空返回其他)
    原文地址:Kotlin语法糖(对象不为空返回自身,为空返回其他)-Stars-One的杂货小窝开发中,经常会有这样逻辑:判断对象如果不为空,则取对象本身;为空,则得到其他对象;然后每次写个if还是有些啰嗦,可以使用kotlin的语法糖可空对象使用?:如果是可空对象,可以使用?:来实现原......
  • C++面向对象技术与C++课程设计任务书[2023-06-23]
    C++面向对象技术与C++课程设计任务书[2023-06-23]面向对象技术与C++课程设计任务书题目1 小型学籍管理系统班级 21060101~02 指导教师 耿军雪姓名 学号 地点 G1-203 完成时间 2023/6/262023/6/30【目的与要求】1、目的:(1)要求学生达到熟练掌握C++语言的基本知识和技能;(2)基......
  • 锁的划分 Synchronized ReentrantLock区别
    共享锁多个事务的读操作可以同时进行,互不阻塞,但某个事务持有共享锁,其他事务不允许修改如readWriteTrantLock就是共享锁排他锁当前持有锁的事务没有完成前,其他事务读、写都会阻塞。这样就能确保在给定时间内,只有一个事务能执行写入如ReentrantLock、就是排他锁 在非Seriali......
  • golang 给对象的基础数据类型的指针类型的属性赋值
    概要有时我们可能碰到定义成下面这样的结构体,结构体里某些属性是基础数据类型,更确切的说,是基础数据类型的指针类型。typeStudentstruct{ namestring`json:"name"` age*int`json:"age"`//age是整型指针}不可行的写法此时该如何对这种成员属性进行赋值呢,下面......
  • es多字段查询:queryString
      https://blog.csdn.net/zl18603543572/article/details/129629817 ......
  • 使用 python 插入 sql 字符串时将对象转换为元组插入占位符
    sql插入的值肯定是动态的,通过%s占位符插入变量:definsert_cover(data:pojos.Cover):sql="insertintocovers(temp,accel_x,accel_y,accel_z,cover_status,date,name,sno)values(%s,%s,%s,%s,%s,%s,%s,%s)"exeSql(sql,tuple(data))data是一个......
  • PostgreSQL合并多行数据为一行,string_agg函数
    通过id列来聚合belong_user_saved列,应用string_agg函数,只要id一样则把第二列通过逗号连接起来聚合前:聚合后:SELECT C.ID, string_agg(u.name::varchar,',')belong_user_savedFROM customerC leftjoincustomer_territoryctonct.customer=c.id leftjoinuser_......
  • PostgreSql的聚合函数--string_agg
    聚合函数顾名思义,聚合函数就是类似于min(),max(),sum()等函数,当然这些都是SQL标准的函数,应该都是比较熟悉,也比较常见。这边不对这些常见的函数进行介绍,主要涉及的是PostgreSql自带的一些特色聚合函数进行介绍,自己学习,也与大家共享。主要介绍的聚合函数:String_agg,xmlagg,array_ag......
  • 序列化和反序列化以及创建对象的几种方式
    如何将对象中的信息永久保存1.将来将对象信息存入数据库2.java中提供的序列化方式来永久保存数据序列化流的概述所谓的序列化:就是把对象通过流的方式存储到文件中.注意:此对象要重写Serializable接口才能被序列化packageorg.westos.Demo;importjava.io.*;publiccl......
  • AQS&&ReentrantLock
    参考:https://www.bilibili.com/video/BV15T4y1U71R/?spm_id_from=333.999.0.0&vd_source=46d50b5d646b50dcb2a208d3946b1598......