ChatGPT在连续追问下对多线程和双重检查锁模式的理解--已经超越中级程序员

news/2024/4/25 12:19:54/文章来源:https://blog.csdn.net/chenhaiming123/article/details/130325214

一、问:

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语句可能存在线程安全问题,正确的实现需要考虑到相应的线程安全措施。

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

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ubuntu 3060显卡驱动+cuda+cudnn+pytorch+pycharm+vscode

文章目录 运行环境&#xff1a;适用&#xff1a;思路&#xff1a;1.1 3060显卡驱动自动安装2.1 CUDA11.1.11)下载CUDA Toolkit 11.1 Update 1 Downloads2)contunue , 然后accept3)回车取消Driver安装&#xff0c;然后install4)添加环境变量5)确认是否安装成功 3.1 cudnn 8.1.11…

【Cartopy基础入门】如何更好的确定边界显示

原文作者&#xff1a;我辈理想 版权声明&#xff1a;文章原创&#xff0c;转载时请务必加上原文超链接、作者信息和本声明。 Cartopy基础入门 【Cartopy基础入门】Cartopy的安装 【Cartopy基础入门】Geojson数据的加载 【Cartopy基础入门】如何更好的确定边界显示 文章目录 Ca…

【边缘计算】登临(Goldwasser-UL64)BW-BR2边缘设备配置指南

目录 开箱配置激活SDK环境测试cuda兼容性 开箱配置 更改盒子root用户密码&#xff1a; sudo passwd root(密码同为root) 切换到root用户身份&#xff1a; su root查看ssh的状态&#xff0c;没有返回说明没有启动 sudo ps -e|grep ssh此时说明ssh服务已启动。 更改ssh配置文…

java定位系统源码,通过独特的射频处理,配合先进的位置算法,可以有效计算出复杂环境下的人员与物品的活动信息

智慧工厂人员定位系统源码&#xff0c;区域电子围栏管控源码 文末获取联系&#xff01; 在工厂日常生产活动中&#xff0c;企业很难精准地掌握访客和承包商等各类人员的实际位置&#xff0c;且无法实时监控巡检人员的巡检路线&#xff0c;当厂区发生灾情或其他异常状况时&#…

postman安装

目录 下载、安装 Postman是一款功能强大的网页调试与发送网页HTTP请求的Chrome插件。 Postman原是Chrome浏览器的插件&#xff0c;可以模拟浏览器向后端服务器发起任何形式(如:get、post)的HTTP请求 使用Postman还可以在发起请求时&#xff0c;携带一些请求参数、请求头等信息…

WebSocket+Vue+SpringBoot实现语音通话

参考文章 整体思路 前端点击开始对话按钮后&#xff0c;将监听麦克风&#xff0c;获取到当前的音频&#xff0c;将其装化为二进制数据&#xff0c;通过websocket发送到webscoket服务端&#xff0c;服务端在接收后&#xff0c;将消息写入给指定客户端&#xff0c;客户端拿到发送…

日本PSE认证日本的電気用品安全法METI备案

日本的電気用品安全法&#xff08;PSE认证&#xff09;法规要求日本的采购商在购进商品后一个月内必须向日本METI注册申报&#xff0c;并必须将采购商名称或ID标在产品上&#xff0c;以便在今后产品销售过程中进行监督管理&#xff0c;完成后将获得電気用品製造事業届出書&…

Java基础学习(10)

Java基础学习 一、JDK8时间类1.1 Zoneld时区1.2 Instant时间戳1.3 ZonedDateTime1.4 DateTimeFormatter1.5 日历类时间表示1.6 工具类1.7 包装类JDK5提出的新特性Integer成员方法 二、集合进阶2.1 集合的体系结构2.1.1 Collection 2.2collection的遍历方式2.2.1 迭代器遍历2.2.…

元宇宙场景下的实时互动RTI技术能力构建

元宇宙可谓是处在风口浪尖&#xff0c;无数的厂商都对元宇宙未来抱有非常美好的憧憬。正因如此&#xff0c;许许多多厂商都在用他们自己的方案&#xff0c;为元宇宙更快、更好的实现&#xff0c;在自己的领域贡献力量。LiveVideoStack 2022北京站邀请到了 ZEGO 即构科技的解决方…

17.集合

集合 集合类是Java数据结构的实现。Java的集合类是java.util包中的重要内容&#xff0c;它允许以各种方式将元素分组&#xff0c;并定义了各种使这些元素更容易操作的方法。Java集合类是Java将一些基本的和使用频率极高的基础类进行封装和增强后再以一个类的形式提供。集合类是…

【Vue2源码】响应式原理

【Vue2源码】响应式原理 文章目录 【Vue2源码】响应式原理Vue响应式的核心设计思路整体流程响应式中的关键角色检测变化注意事项响应式原理数据观测重写数组7个变异方法增加__ob__属性__ob__有两大用处&#xff1a; Vue.js 基本上遵循 MVVM&#xff08;Model–View–ViewModel&…

【Cartopy基础入门】如何丝滑的加载Geojson数据

原文作者&#xff1a;我辈李想 版权声明&#xff1a;文章原创&#xff0c;转载时请务必加上原文超链接、作者信息和本声明。 Cartopy基础入门 【Cartopy基础入门】Cartopy的安装 【Cartopy基础入门】如何丝滑的加载Geojson数据 文章目录 Cartopy基础入门一、Geojson数据来源二…

camunda的manual task节点用途

Camunda的Manual Task用于在流程中暂停执行&#xff0c;直到人工干预完成某个任务。与User Task不同&#xff0c;Manual Task没有分配给特定用户或用户组&#xff0c;而是需要手动启动并指定下一步流程。 Manual Task可以用于以下场景&#xff1a; 1、流程执行需要等待人工干…

安全狗入选2023年福建省数字经济核心产业领域创新企业名单

近日&#xff0c;福建省数字福建建设领导小组办公室公布了入选2023年全省数字经济核心产业领域创新企业名单。 作为国内云原生安全领导厂商&#xff0c;安全狗凭借综合表现与优势入选名单&#xff0c;荣膺“未来独角兽”称号。 据悉&#xff0c;此次对“未来独角兽”的评选条件…

Linux文件类型与属性

一、文件类型 Linux 系统下一共分为 7 种文件类型。通过 stat 命令或者 ls 命令来查看文件类型。 - &#xff1a;普通文件 d &#xff1a;目录文件 c &#xff1a;字符设备文件 b &#xff1a;块设备文件 l &#xff1a;符号链接文件 s &#xff1a;套接字文件 p &…

线性模型的介绍

一、背景 在一个理想的连续世界中&#xff0c;任何非线性的东西都可以被线性的东西来拟合&#xff0c;所以理论上线性模型可以模拟物理世界中的绝大多数现象。 线性模型&#xff08;Linear Model&#xff09;是机器学习中应用最广泛的模型&#xff0c;指通过样本特征的线性组…

【并发基础】一篇文章带你彻底搞懂Java线程中断的底层原理——interrupt()、interrupted()、isInterrupted()

目录 〇、Java线程中断与阻塞的区别 0.1 线程中断 0.2 线程阻塞 一、线程的中断 二、中断方法 2.1 void interrupt() 2.1.1 可中断的阻塞 2.1.2 不可中断的阻塞 2.1.3 实践案例 2.2 boolean isInterrupted() 2.3 boolean interrupted() 2.4 代码案例 三、源码分析…

指定GPU运行python程序

一、命令行运行python程序时 1、首先查看哪些GPU空闲&#xff0c;nvidia-smi显示当前GPU使用情况。 nvidia-smiGPU&#xff1a;编号&#xff0c;这里是0和1 Fan&#xff1a;风扇转速&#xff0c;在0到100%之间变动&#xff0c;第一个是29% Name&#xff1a;显卡名&#xff…

部署LVS-NAT群集实验

一、 实验准备 负载调度器&#xff1a;内网关 ens33&#xff1a;192.168.109.12&#xff0c;外网关 ens37&#xff1a;12.0.0.1外网 Web节点服务器1&#xff1a;192.168.109.13 Web节点服务器2&#xff1a;192.168.109.14 NFS服务器&#xff1a;192.168.109.11 客户端&#xf…

基于 Windows 安装 ESP32 Arduino 软件开发环境

ESP32 Arduino 源码库&#xff1a;arduino-esp32ESP32 Arduino 环境搭建说明&#xff1a;About Arduino ESP32 其他软件环境需求&#xff1a; Git 环境 1、安装 Arduino 软件 可在 Arduino 官网 获取 Windows 端 Arduino 安装包&#xff0c;如下&#xff1a; 使用如下 .exe 一…