ChatGPT在连续追问下对多线程和双重检查锁模式的理解--已经超越中级程序员
一、问:
private static final Map<Method, GZHttpClientResultModel> CACHE_RESULT_MODEL = new ConcurrentHashMap<>();public void abc(Method method){cacheResultMode(method);GZHttpClientResultModel model = CACHE_RESULT_MODEL.get(method);}private void cacheResultMode(Method method) {if (CACHE_RESULT_MODEL.containsKey(method)) {log.info("-----第一次contains{}", method.getName());return;}safeCacheResultMode(method);}private synchronized void safeCacheResultMode(Method method) {if (CACHE_RESULT_MODEL.containsKey(method)) {log.info("-----第二次contains{}", method.getName());return;}log.info("-----需要put{}", method.getName());Type returnType = method.getGenericReturnType();CACHE_RESULT_MODEL.put(method, new GZHttpClientResultModel(returnType));}
分析这段代码多线程情况下model为空
二、ChatGPT答:
在多线程情况下,可能会出现GZHttpClientResultModel model为null的情况,因为CACHE_RESULT_MODEL是一个ConcurrentHashMap对象,虽然它本身是线程安全的,但是它内部的操作不是完全线程安全的。
比如在cacheResultMode方法中,如果两个线程同时接近CACHE_RESULT_MODEL.containsKey(method)这行代码,他们可能同时得到false,然后接下来会同时执行safeCacheResultMode方法。假设此时线程1已经进入synchronized安全锁中,而线程2则处于waiting(等待)状态。如果此时线程3又在同样的时间内到达了第一个contains检查,由于线程1已经加锁,线程3在得到false的结果后也会执行safeCacheResultMode。
这就意味着在多线程情况下,可能会有多个线程同时执行safeCacheResultMode方法,就会多次向cacheResultMode中的map添加新的元素,而只有一个线程的结果会真正地添加到map中,这样其他线程就会得到一个null的结果。
为了解决这个问题,可以在safeCacheResultMode方法上添加synchronized关键字,来保证只有一个线程能够执行添加操作。这样做可以确保在添加元素时不会有竞争条件的情况发生,从而保证了结果的正确性。
三、继续问:
safeCacheResultMode方法上已经添加synchronized关键字了
四、ChatGPT答:
如果已经在safeCacheResultMode方法上添加了synchronized关键字,就可以优化代码,将cacheResultMode方法中的containsKey方法也改为synchronized方法,这样可以确保在多线程环境下只有一个线程能够执行该方法,避免竞争条件。以下是修改后的代码:```
private static final Map<Method, GZHttpClientResultModel> CACHE_RESULT_MODEL = new ConcurrentHashMap<>();public void abc(Method method){cacheResultMode(method);GZHttpClientResultModel model = CACHE_RESULT_MODEL.get(method);}private synchronized void cacheResultMode(Method method) {if (CACHE_RESULT_MODEL.containsKey(method)) {log.info("-----第一次contains{}", method.getName());return;}safeCacheResultMode(method);
}private synchronized void safeCacheResultMode(Method method) {if (CACHE_RESULT_MODEL.containsKey(method)) {log.info("-----第二次contains{}", method.getName());return;}log.info("-----需要put{}", method.getName());Type returnType = method.getGenericReturnType();CACHE_RESULT_MODEL.put(method, new GZHttpClientResultModel(returnType));
}
```这样做可以确保在多线程环境下执行cacheResultMode方法时,只有一个线程能够执行该方法,从而避免了多个线程同时向map中添加元素的问题。此外,由于CACHE_RESULT_MODEL是ConcurrentHashMap对象,多个线程可以同时读取该对象的内容,因此不需要在获取元素时添加synchronized关键字。
五、问:
高并发情况cacheResultMode会变得很慢,希望在safeCacheResultMode做串行,cacheResultMode调用多次话可以直接返回不用排队
六、ChatGPT答:
在高并发情况下,如果cacheResultMode方法中的containsKey方法一直被调用,就会严重影响程序的性能。为了解决这个问题,可以使用Double Checked Locking技术,即在方法内部使用一个局部变量来保存结果,避免重复调用safeCacheResultMode方法,从而提高程序的性能。以下是修改后的代码:```
private static final Map<Method, GZHttpClientResultModel> CACHE_RESULT_MODEL = new ConcurrentHashMap<>();public void abc(Method method){GZHttpClientResultModel model = CACHE_RESULT_MODEL.get(method);if(model == null){cacheResultMode(method);model = CACHE_RESULT_MODEL.get(method);}
}private void cacheResultMode(Method method) {if (CACHE_RESULT_MODEL.containsKey(method)) {log.info("-----第一次contains{}", method.getName());return;}safeCacheResultMode(method);
}private synchronized void safeCacheResultMode(Method method) {if (CACHE_RESULT_MODEL.containsKey(method)) {log.info("-----第二次contains{}", method.getName());return;}log.info("-----需要put{}", method.getName());Type returnType = method.getGenericReturnType();CACHE_RESULT_MODEL.put(method, new GZHttpClientResultModel(returnType));
}
```在这个版本的代码中,当需要获取结果时,首先尝试从CACHE_RESULT_MODEL中获取结果。如果获取结果失败,则调用cacheResultMode方法,该方法会先尝试从CACHE_RESULT_MODEL中获取结果,如果获取失败,则调用safeCacheResultMode方法来生成结果。由于safeCacheResultMode方法已经添加了synchronized关键字,因此在多线程环境下只有一个线程能够执行该方法,避免了竞争条件的发生。通过这种方法,可以避免在高并发场景下多次调用safeCacheResultMode方法,从而提高了程序的性能。同时,由于尝试获取结果时并没有使用synchronized关键字来保证线程安全,因此可以同时服务多个线程,从而增加了程序的并发性。
七、继续问:
直接cacheResultMode后再进行CACHE_RESULT_MODEL.get(method)可以直接拿到结果,不需要进行判断
八、ChatGPT答:
您是对的,如果在cacheResultMode方法中执行了safeCacheResultMode方法,并且确保CACHE_RESULT_MODEL中已经存在了指定的键值对,那么在调用CACHE_RESULT_MODEL.get方法时就可以直接拿到结果,而不需要再次进行判断。以下是更新后的代码:```
private static final Map<Method, GZHttpClientResultModel> CACHE_RESULT_MODEL = new ConcurrentHashMap<>();public void abc(Method method){cacheResultMode(method);GZHttpClientResultModel model = CACHE_RESULT_MODEL.get(method);
}private void cacheResultMode(Method method) {if (CACHE_RESULT_MODEL.containsKey(method)) {log.info("-----已经存在{}", method.getName());return;}log.info("-----需要put{}", method.getName());Type returnType = method.getGenericReturnType();CACHE_RESULT_MODEL.put(method, new GZHttpClientResultModel(returnType));
}
```在这个版本的代码中,cacheResultMode方法首先尝试从CACHE_RESULT_MODEL中获取结果。如果获取失败,则执行相应的业务逻辑,并且在CACHE_RESULT_MODEL中添加相应的键值对。在获取结果时,直接执行CACHE_RESULT_MODEL.get方法,而不需要再次进行判断。这种方法的优点是,在保证线程安全的同时,可以减少判断的次数,从而提高程序的性能。同时,由于ConcurrentHashMap可以同时支持多个线程的访问,因此可以并发处理多个请求,提高程序的并发性。
九、问:
高并发场景下CACHE_RESULT_MODEL.get(method)不会为null
十、ChatGPT答:
在高并发场景下,确实很难出现CACHE_RESULT_MODEL.get(method)为null的情况。因为ConcurrentHashMap是线程安全的,多个线程可以同时操作该对象,因此在多线程环境下,调用CACHE_RESULT_MODEL.get方法获取元素时,基本上不会返回null。然而,在某些极端的情况下,可能会出现null的情况。例如,当程序在初始化CACHE_RESULT_MODEL对象时,如果存在多个线程同时调用该方法,并且第一个线程还没有将键值对加入到map中,而第二个线程又开始获取值,此时就有可能出现null的情况。为了避免这种情况的发生,可以使用双重校验锁的机制,即在cacheResultMode方法中再次判断CACHE_RESULT_MODEL是否包含指定的键值对,如果不存在,则调用safeCacheResultMode方法进行加锁操作。在safeCacheResultMode方法中,同样需要再次判断CACHE_RESULT_MODEL是否包含指定的键值对。以下是更新后的代码:```
private static final Map<Method, GZHttpClientResultModel> CACHE_RESULT_MODEL = new ConcurrentHashMap<>();public void abc(Method method){GZHttpClientResultModel model = CACHE_RESULT_MODEL.get(method);if(model == null){cacheResultMode(method);model = CACHE_RESULT_MODEL.get(method);}
}private void cacheResultMode(Method method) {GZHttpClientResultModel model = CACHE_RESULT_MODEL.get(method);if(model == null){synchronized(CACHE_RESULT_MODEL) {model = CACHE_RESULT_MODEL.get(method);if(model == null){log.info("-----需要put{}", method.getName());Type returnType = method.getGenericReturnType();CACHE_RESULT_MODEL.put(method, new GZHttpClientResultModel(returnType));}}}
}
```在这个版本的代码中,cacheResultMode方法首先尝试从CACHE_RESULT_MODEL中获取结果。如果获取失败,则执行相应的业务逻辑。在执行业务逻辑时,首先再次尝试从CACHE_RESULT_MODEL中获取结果,如果获取失败,则使用synchronized关键字将代码块进行加锁操作,创建并添加新的键值对。通过这种方法,可以确保在高并发环境下,即使多个线程同时调用cacheResultMode方法,也可以避免CACHE_RESULT_MODEL.get方法返回null的情况。同时,由于使用了双重校验锁的机制,程序的性能也得到了提高。但需要注意的是,双重校验锁并不适用于所有场景,需要根据实际情况进行考虑。
十一、问:
private static final Map<Method, GZHttpClientResultModel> CACHE_RESULT_MODEL = new ConcurrentHashMap<>();public void abc(Method method){cacheResultMode(method);GZHttpClientResultModel model = CACHE_RESULT_MODEL.get(method);}private void cacheResultMode(Method method) {if (CACHE_RESULT_MODEL.containsKey(method)) {log.info("-----第一次contains{}", method.getName());return;}safeCacheResultMode(method);}private synchronized void safeCacheResultMode(Method method) {if (CACHE_RESULT_MODEL.containsKey(method)) {log.info("-----第二次contains{}", method.getName());return;}log.info("-----需要put{}", method.getName());Type returnType = method.getGenericReturnType();CACHE_RESULT_MODEL.put(method, new GZHttpClientResultModel(returnType));}
这段代码多线程情况下model为空,分析原因
十二、ChatGPT答:
在多线程环境下,如果多个线程同时调用abc方法,可能会导致GZHttpClientResultModel对象为空的情况。例如,当线程1和线程2同时调用abc方法,同时发现CACHE_RESULT_MODEL中不包含指定的键值对。线程1执行cacheResultMode方法,进入synchronized块,执行safeCacheResultMode方法,并且向CACHE_RESULT_MODEL中添加了新的键值对。此时,线程2也进入了synchronized块,此时CACHE_RESULT_MODEL已经包含了指定的键值对,因此直接返回。然后线程1执行完毕,线程2返回到abc方法中,调用get方法获取值,此时获取到的是null值。因此,可以看出,多线程环境下,由于没有在get方法和put方法中使用同步锁(例如synchronized关键字),可能会导致线程安全问题。要解决这个问题,有几个解决方案:1. 将整段代码使用synchronized进行同步锁控制,确保在多线程环境下只有一个线程能够访问CACHE_RESULT_MODEL对象。
```private static final Map<Method, GZHttpClientResultModel> CACHE_RESULT_MODEL = new ConcurrentHashMap<>();public synchronized void abc(Method method){cacheResultMode(method);GZHttpClientResultModel model = CACHE_RESULT_MODEL.get(method);}private void cacheResultMode(Method method) {synchronized(CACHE_RESULT_MODEL) {if (CACHE_RESULT_MODEL.containsKey(method)) {log.info("-----第一次contains{}", method.getName());return;}safeCacheResultMode(method);}}private void safeCacheResultMode(Method method) {synchronized(CACHE_RESULT_MODEL) {if (CACHE_RESULT_MODEL.containsKey(method)) {log.info("-----第二次contains{}", method.getName());return;}log.info("-----需要put{}", method.getName());Type returnType = method.getGenericReturnType();CACHE_RESULT_MODEL.put(method, new GZHttpClientResultModel(returnType));}}
```
但是这种并不是最优解,因为使用synchronized会降低多线程环境下的并发性能。2. 使用ConcurrentHashMap.replace方法,该方法可以在并发情况下,只有在指定键的值是指定值时才进行替换,从而避免线程安全问题,提高并发性能。例如:```private static final Map<Method, GZHttpClientResultModel> CACHE_RESULT_MODEL = new ConcurrentHashMap<>();public void abc(Method method){cacheResultMode(method);GZHttpClientResultModel model = CACHE_RESULT_MODEL.get(method);}private void cacheResultMode(Method method) {while (true) {GZHttpClientResultModel model = CACHE_RESULT_MODEL.get(method);if (model == null) {log.info("-----需要put{}", method.getName());Type returnType = method.getGenericReturnType();GZHttpClientResultModel newModel = new GZHttpClientResultModel(returnType);if (CACHE_RESULT_MODEL.replace(method, null, newModel)) {break;}} else {break;}}}
```在这个版本的代码中,cacheResultMode方法使用循环来获取指定键值对的值,如果获取到的值是null,则尝试使用ConcurrentHashMap.replace方法进行替换。由于该方法仅在当前键的值是null时才进行替换,因此可以避免线程安全问题。同时,由于ConcurrentHashMap是线程安全的,因此多个线程可以同时操作该对象,从而提高程序的并发性能。
十三、问:
private static final Map<Method, GZHttpClientResultModel> CACHE_RESULT_MODEL = new ConcurrentHashMap<>();public void abc(Method method){cacheResultMode(method);GZHttpClientResultModel model = CACHE_RESULT_MODEL.get(method);}private void cacheResultMode(Method method) {if (CACHE_RESULT_MODEL.containsKey(method)) {log.info("-----第一次contains{}", method.getName());return;}safeCacheResultMode(method);}private synchronized void safeCacheResultMode(Method method) {if (CACHE_RESULT_MODEL.containsKey(method)) {log.info("-----第二次contains{}", method.getName());return;}log.info("-----需要put{}", method.getName());Type returnType = method.getGenericReturnType();CACHE_RESULT_MODEL.put(method, new GZHttpClientResultModel(returnType));}
这段代码有双重检查锁机制吗
十四、ChatGPT答:
这段代码没有双重检查锁机制。虽然代码中cacheResultMode方法和safeCacheResultMode方法都使用了if语句来进行判断,但是不满足双重检查锁定模式的条件,即在获取对象之前和在同步代码块之外进行了两次检查。双重检查锁定模式通常指的是在同步代码块内和同步代码块外分别进行两次检查,以确保在多线程环境下只有一个线程能够访问该对象。例如:```
private static volatile Singleton instance;public static Singleton getInstance() {if (instance == null) {synchronized (Singleton.class) {if (instance == null) {instance = new Singleton();}}}return instance;
}
```在这个版本的代码中,首先检查instance是否为null,在同步代码块中再次检查instance是否为null,如果是,则创建一个新的Singleton对象,并将其分配给instance变量。使用volatile关键字修饰instance变量,可以确保将instance变量的值在多线程环境中正确的传递。总体来说,双重检查锁定模式可以提高多线程环境下的性能和并发性,但是需要注意在实现时要注意线程安全的问题。
十五、问:
在cacheResultMode判断了CACHE_RESULT_MODEL,在synchronized方法也判断了CACHE_RESULT_MODEL为什么不是双重检查锁
十六、ChatGPT答:
确实,代码中使用了两个if语句来判断CACHE_RESULT_MODEL中是否包含指定的键值对,并在synchronized方法内进行了加锁操作,这看起来很像双重检查锁(Double Checked Locking)模式。
但是,双重检查锁模式在DCL的实现中,需要在synchronized块内部进行第二次检查。在代码中synchronized块内部虽然也有检查,但是仅仅只是一个简单的if语句,并没有像双重检查锁模式那样进行第二次判断。
因此,这段代码虽然做了两次判断,但是并不是双重检锁机制,而是通过两个if语句来确保CACHE_RESULT_MODEL中不会重复添加同一个键值对,因此可以避免线程安全问题。同时,在synchronized方法中使用了同步锁加锁操作,保证在多线程环境下只有一个线程能够访问CACHE_RESULT_MODEL对象。
虽然这种写法没有严格意义上的双重检查锁定模式,但是应该可以满足实际的需求。
十七、问:
双重检查锁代码块也仅仅只是一个简单的if语句判断
十八、ChatGPT答:
您提出了一个很好的观点,确实,正确的双重检查锁定模式需要在同步代码块中进行第二次判断,但是如果第二次判断也是一个简单的if语句,可能会存在线程安全问题。考虑以下代码示例:```
private static volatile Singleton instance;public static Singleton getInstance() {if (instance == null) {synchronized (Singleton.class) {if (instance == null) {instance = new Singleton();}}}return instance;
}
```这是一个标准的双重检查锁定模式的实现,但是在第二次判断中,只是简单地判断了instance是否为null,这存在一定的线程安全问题。实际上,在多线程环境下,第二个if语句可能会出现失效的情况,例如在一个线程进入同步块时已经创建了一个实例,而另一个线程在同步块外等待时同样检查到instance为null,然后它们都会尝试创建一个实例,从而导致实例被创建了两次。为了解决这个问题,可以使用volatile关键字来保证可见性和禁止重排序,从而确保在多线程环境下只有一个线程能够访问该对象,并且实例只会创建一次。所以,确实,只是简单的if语句可能存在线程安全问题,正确的实现需要考虑到相应的线程安全措施。
相关文章:

ChatGPT在连续追问下对多线程和双重检查锁模式的理解--已经超越中级程序员
一、问: private static final Map<Method, GZHttpClientResultModel> CACHE_RESULT_MODEL new ConcurrentHashMap<>();public void abc(Method method){cacheResultMode(method);GZHttpClientResultModel model CACHE_RESULT_MODEL.get(method);}pr…...

每天一道大厂SQL题【Day22】华泰证券真题实战(四)
每天一道大厂SQL题【Day22】华泰证券真题实战(四) 大家好,我是Maynor。相信大家和我一样,都有一个大厂梦,作为一名资深大数据选手,深知SQL重要性,接下来我准备用100天时间,基于大数据岗面试中的经典SQL题&…...

【智能电网】智能电网中针对DOS和FDIA的弹性分布式EMA(Matlab代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...

IDEA 创建微服务项目实例
🎈 作者:Linux猿 🎈 简介:CSDN博客专家🏆,华为云享专家🏆,Linux、C/C++、云计算、物联网、面试、刷题、算法尽管咨询我,关注我,有问题私聊! 🎈 关注专栏:C/C++面试通关【精讲】 优质好文持续更新中……🚀🚀🚀 🎈 欢迎小伙伴们点赞👍、收藏⭐、留…...

注册苹果开发者账号的方法
在2020年以前,注册苹果开发者账号后,就可以生成证书。 但2020年后,因为注册苹果开发者账号需要使用Apple Developer app注册开发者账号,所以需要缴费才能创建ios证书了。 所以新政策出来后,注册苹果开发者账号&#…...

OpenCV2 计算机视觉应用编程秘籍:1~5
原文:OpenCV2 Computer Vision Application Programming Cookbook 协议:CC BY-NC-SA 4.0 译者:飞龙 本文来自【ApacheCN 计算机视觉 译文集】,采用译后编辑(MTPE)流程来尽可能提升效率。 当别人说你没有底线…...

Domino自带的JSON校验工具
大家好,才是真的好。 JSON数据在Notes/Domino已经变得非常重要。从Domino 10开始,在LotusScript语言中就加入了对JSON数据处理功能。在管理中,我们知道,从Domino 12版本开始就支持Domino自动化配置,也是使用JSON数据作…...

CentOS(linux)使用Docker安装nacos
1. 拉取nacos镜像 docker pull nacos/nacos-server:2.0.3 2. 创建所需文件夹(以安装在home目录下为例) 1) 创建conf文件夹 mkdir -p /home/nacos/conf a. 新增文件application.properties(或者不增加该文件,会使用默认的) 文件内容如下: # spring server.servlet.contextP…...

无线测温在线监测系统工作原理与产品选型
摘要:本文首先介绍了无线测温在线监测系统的基本工作原理以及软硬件组成,重点介绍了在线监测的无线测温技术特点。在此研究基础上,探讨了无线测温在线监测系统在实际工作场景中的应用案例,证明了其在温度检测方面的重要应用价值。…...

Nginx rewrite ——重写跳转
Nginx常见模块 http http块是Nginx服务器配置中的重要部分,代理、缓存和日志定义等绝大多数的功能和第三方模块的配置都可以放在这模块中。作用包括:文件引入、MIME-Type定义、日志自定义、是否使用sendfile传输文件、连接超时时间、单连接请求数上限等…...

【华为OD机试真题 C++】1038 - 全量和已占用字符集 | 机试题+算法思路+考点+代码解析
文章目录 一、题目🔸题目描述🔸输入输出🔸样例1二、代码参考作者:KJ.JK🌈 🌈 🌈 🌈 🌈 🌈 🌈 🌈 🌈 🌈 🌈 🌈 🌈 🍂个人博客首页: KJ.JK 💖系列专栏:华为OD机试真题(C++) 一、题目 🔸题目描述 所谓水仙花数,是指一个n位的正整数…...

网络中的网关和物联网的网关区别 局域网 路由器 交换机 服务器
网关:是个概念。连接两种不同的网络。例如局域网要与外部通信,需要经过网关。 设备和设备之间的通信,转换协议需要网关 路由器里有功能是对网关这个概念的实现。 所以网关它可以是路由器,交换机或者是PC。 路由器有网关功能&a…...

2023 年嵌入式世界的3 大趋势分析
目录 大家好,本文讲解了嵌入式发展的3个大趋势,分享给大家。 趋势#1 – Visual Studio Code Integration 趋势#2 –支持“现代”软件流程 趋势 #3 – 在设计中利用 AI 和 ML 结论 大家好,本文讲解了嵌入式发展的3个大趋势,分享…...

基于 DolphinDB 机器学习的出租车行程时间预测
DolphinDB 集高性能时序数据库与全面的分析功能为一体,可用于海量结构化数据的存储、查询、分析、实时计算等,在工业物联网场景中应用广泛。本文以纽约出租车行程时间预测为例,介绍如何使用 DolphinDB 训练机器学习模型,并进行实时…...

Python调用最小二乘法
文章目录 numpy实现scipy封装速度对比 所谓线性最小二乘法,可以理解为是解方程的延续,区别在于,当未知量远小于方程数的时候,将得到一个无解的问题。最小二乘法的实质,是保证误差最小的情况下对未知数进行赋值。 最小…...

15.数据表格.上
本节课我们来开始了解 Layui 的内置模块:table 数据表格。 一.基本使用 1. table 模块,通过异步加载数据来渲染表格来展现数据内容; <table id"table"></table> layui.use([table], () > { const table …...

在poetry虚拟环境下打包exe
本博客介绍了在poetry虚拟环境下打包exe的流程,包含两个部分 打包的基本流程打包过程中遇到的问题 打包的基本流程 copy打包工具到本地,(share:\公用共享\芯片部\乔羽\img_generate\系统部提供的打包exe工具) 用poetry搭建虚拟环境 在打包…...

【Unity VR开发】结合VRTK4.0:高亮与标签
语录: 信仰到底是什么呢,就是纵身一跃,就是我们跟神之间一个永远的约定,是舍弃日的去开始新的生活;信仰就是从今以后,再也不要放开你的手。 前言: Interactable Highlighter :当我们的手柄触碰…...

有了MySQL,为什么还要有NoSQL
🏆今日学习目标: 🍀MySQL和NoSQL的区别 ✅创作者:林在闪闪发光 ⏰预计时间:30分钟 🎉个人主页:林在闪闪发光的个人主页 🍁林在闪闪发光的个人社区,欢迎你的加入: 林在闪闪…...

找PPT模板就上这5个网站~
分享几个可以永久免费下载PPT模板、素材的网站,上万个模板随便下载,赶紧收藏起来~ 1、菜鸟图库 https://www.sucai999.com/search/ppt/0_0_0_1.html?vNTYxMjky 网站素材非常全面,主要以设计类素材为主,办公类素材也很多&#x…...

Ae:摄像机选项
摄像机选项 Camera Options 快捷键:AA 摄像机选项 Camera Options与“摄像机设置”中的参数大同小异且同步变化,额外增加了一些与镜头模糊和散景光斑形状有关的摄像机属性。 请参阅: 《Ae:摄像机设置》 在合成设置中,选…...

嵌入式日志库ulog的使用和解析
嵌入式日志信息保存调试(ulog) 获取 项目地址:https://github.com/rdpoor/ulog uLog 为嵌入式微控制器或任何资源有限的系统提供结构化的日志记录机制。它继承了流行的 Log4c 和 Log4j 平台背后的一些概念,但开销更低。 使用方…...

自阿里P8爆出内部1031道java面试题后,在Boss直聘狂拿千份Offer
开始之前我问大家几个问题,看大家是如何思考的: 1.程序员一定要去一线城市漂泊吗?在自己家乡如何拿到一份满意的薪水? 2.程序员被裁员、找不到工作,代表什么? 3.程序员一定要进一线大厂吗?你…...

Java最新面试题100道,包含答案示例(41-50题)
非常抱歉,我理解有误。以下是第41至45题的Java面试题和答案: 请问Java中有哪些常用的集合类型? 答:Java中有多种常用的集合类型,包括List、Set、Map等。其中,List和Set分别代表一组元素的序列和一组无序不…...

C++之深入解析野指针和悬空指针
一、野指针 ① 什么是野指针? 野指针指向一个已删除的对象或未申请访问受限内存区域的指针。与空指针不同,野指针无法通过简单地判断是否为NULL避免,而只能通过养成良好的编程习惯来尽力减少,对野指针进行操作很容易造成程序错误…...

YOLOv7+单目测距(python)
YOLOv7单目测距(python) 1. 相关配置2. 测距原理3. 相机标定3.1:标定方法13.2:标定方法2 4. 相机测距4.1 测距添加4.2 主代码 5. 实验效果 相关链接 1. YOLOV5 单目测距(python) 2. YOLOV5 单目跟踪&…...

SYSU程设c++(第九周)函数对象、友元函数、友元类
函数对象: 如果一个类定义了operator()运算符函数,则可以使用该类的对象名为函数名调用这个函数. 函数对象是一个对象,但调用形式和普通函数调用一样,因此取名叫函数对象 (注意operator()先有个括号,接着才是括号(参数…...

Target品质审核零容忍问题点——上篇
【Target品质审核零容忍问题点——上篇】 Target品质验厂审核过程中共有110多个问题点,其中包含零容忍问题12项,审核当天如果出现任何零容忍项或出现很多扣分项,将直接影响最后的结果,极容易导致验厂不通过。建议工厂在遇到Target…...

使用node版本管理器gnvm
目录 一、官网 二、下载 三、查看本机node安装地址 四、将gnvm放到node安装目录 五、安装其他版本node(以管理员身份打开CMD) 六、使用指定版本(以管理员身份打开CMD) 七、查看当前版本(以管理员身份打开CMD&…...

SpringBoot中使用redis事务
本文基于SpringBoot 2.X 事务在关系型数据库的开发中经常用到,其实非关系型数据库,比如redis也有对事务的支持,本文主要探讨在SpringBoot中如何使用redis事务。 事务的相关介绍可以参考: 0、起因 在一次线上事故中,我们…...