【linux 多线程并发】线程属性设置与查看,绑定CPU,线程分离与可连接,避够多线程下的内存泄漏
线程属性设置
专栏内容:
参天引擎内核架构
本专栏一起来聊聊参天引擎内核架构,以及如何实现多机的数据库节点的多读多写,与传统主备,MPP的区别,技术难点的分析,数据元数据同步,多主节点的情况下对故障容灾的支持。手写数据库toadb
本专栏主要介绍如何从零开发,开发的步骤,以及开发过程中的涉及的原理,遇到的问题等,让大家能跟上并且可以一起开发,让每个需要的人成为参与者。
本专栏会定期更新,对应的代码也会定期更新,每个阶段的代码会打上tag,方便阶段学习。
开源贡献:
- toadb开源库
个人主页:我的主页
管理社区:开源数据库
座右铭:天行健,君子以自强不息;地势坤,君子以厚德载物.
文章目录
- 线程属性设置
- 前言
- 概述
- 线程属性
- 栈属性
- 栈地址
- 栈大小
- 栈保护区
- 调度属性
- 继承属性
- 调度策略属性
- 优先级属性
- 调度资源范围属性
- CPU亲和性属性
- 分离属性
- 信号属性
- 默认属性
- 总结
- 结尾
前言
现代的CPU都是多core处理器,而且在intel处理器中每个core又可以多个processor,形成了多任务并行处理的硬件架构,在服务器端的处理器上架构又有一些不同,传统的采用SMP,也就是对称的多任务处理架构,每个任务都可以对等的访问所有内存,外设等,而如今在ARM系列CPU上,多采用NUMA架构,它将CPU核分了几个组,给每个组的CPU core分配了对应的内存和外设,CPU访问对应的内存和外设时速度最优,跨组访问时性能会降底一些。
随着硬件技术的持续发展,它们对一般应用的性能优化能力越来越强,同时对于服务器软件的开发,提出更高要求,要想达到极高的并发和性能,就需要充分利用当前硬件架构的特点,对它们进行压榨。那么,我们的应用至少也是要采用多任务架构,不管是多线程还是多进程的多任务架构,才可以充分利用硬件的资源,达到高效的处理能力。
当然多任务框架的采用,不仅仅是多线程的执行,需要对多任务下带来的问题进行处理,如任务执行返回值获取,任务间数据的传递,任务执行次序的协调;当然也不是任务越多处理越快,要避免线程过多导致操作系统夯住,也要防止任务空转过快导致CPU使用率飙高。
本专栏主要介绍使用多线程与多进程模型,如何搭建多任务的应用框架,同时对多任务下的数据通信,数据同步,任务控制,以及CPU core与任务绑定等相关知识的分享,让大家在实际开发中轻松构建自已的多任务程序。
概述
前一篇博客介绍了创建线程的步骤和调用的接口,但是传递的参数都采用了默认值,其实线程有很多属性值可以进行设置,这样让多线程的应用运行更加的协调,充分利用硬件资源。
本文就来分享一下线程的属性,以及设置方法和接口,最后会分享一段示例代码看一下设置效果。
特点说明一下,这里分享的linux thread 库,是Native Posix Thread Library(NPTL),也就是符合posix的接口;为什么要强调这个呢,因为linux 下的线程库有好几种,各家实现都有一些差异,也会存在一些问题,而posix的这一套NTPL已经被大家广泛接受而大量使用,所以我们也以这套库为基础来介绍;编译时需要加-lptrhead或libpthread库引用。
线程属性
线程属性有很多,这里分类列举一下。
属性名 | 接口 | 描述 |
---|---|---|
栈属性 | pthread_attr_getstack, pthread_attr_setstack | 设置栈地址和栈大小 |
栈地址 | pthread_attr_getstackaddr, pthread_attr_setstackaddr | 设置栈地址 |
栈大小 | pthread_attr_getstacksize, pthread_attr_setstacksize | 设置栈大小 |
堆栈保护区 | pthread_attr_getguardsize, pthread_attr_setguardsize | 设置堆栈保护区大小 |
分离状态 | pthread_attr_getdetachstate, pthread_attr_setdetachstate | 设置线程的可连接或分离 |
调度继承属性 | pthread_attr_getinheritsched, pthread_attr_setinheritsched | 是否继承调度属性的设置 |
调度优先级属性 | pthread_attr_getschedparam, pthread_attr_setschedparam | 调度优先级参数的设置 |
调度策略属性 | pthread_attr_getschedpolicy, pthread_attr_setschedpolicy | 调度策略属性的设置 |
调度资源的范围 | pthread_attr_getscope, pthread_attr_setscope | 设置调度资源的范围 |
CPU 亲和性 | pthread_attr_getaffinity_np,pthread_attr_setaffinity_np | 设置线程运行时绑定的CPU core |
信号掩码 | pthread_attr_getsigmask_np, pthread_attr_setsigmask_np | 信号掩码设置 |
默认属性 | pthread_getattr_default_np, pthread_setattr_default_np | 设置为线程默认属性 |
获取属性 | pthread_getattr_np | 获取线程实际属性 |
主要分为四大类:
- 堆栈相关属性,设置栈大小和起始地址,还可以设置保护区,给越界留有缓冲区;
- 调度相关属性,CPU的绑定,调度策略等;
- 分离状态,对线程退出时,资源的回收方式的设置;
- 信号掩码设置,对线程级别的信号中断响应设置;
栈属性
属性名 | 接口 | 描述 |
---|---|---|
栈属性 | pthread_attr_getstack, pthread_attr_setstack | 设置栈地址和栈大小 |
栈地址 | pthread_attr_getstackaddr, pthread_attr_setstackaddr | 设置栈地址 |
栈大小 | pthread_attr_getstacksize, pthread_attr_setstacksize | 设置栈大小 |
堆栈保护区 | pthread_attr_getguardsize, pthread_attr_setguardsize | 设置堆栈保护区大小 |
主要有四组接口,其中栈属性设置包括了对栈地址和栈大小的设置,所以这里只介绍下面三组接口。
栈地址
int pthread_attr_setstack(pthread_attr_t *attr,void *stackaddr, size_t stacksize);
int pthread_attr_getstack(pthread_attr_t *attr,void **stackaddr, size_t *stacksize);int pthread_attr_getstackaddr(const pthread_attr_t *restrict attr,void **restrict stackaddr);
int pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr);
设置线程栈的起始地址,我们知道栈的地址是从起始地址开始从大到小的增长,也就是向下连续的分配空间,如果该地址超出了分配的栈区域的最高地址,就会发生栈溢出。
不建议平常使用单独设置栈地址的功能 pthread_attr_setstackaddr
,由于无法提供指定增长方向或栈范围的方法; 而pthread_attr_setstack
中指定了起始地址和stacksize参数指定的栈的范围,可以分配连续的向下的区域。
栈大小
int pthread_attr_getstacksize(const pthread_attr_t *restrict attr,size_t *restrict stacksize);
int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize);
常用的是对栈大小的设置,根据程序本身的特点,如并发线程多少,递归调用深度,分配大的结构体数据等情况,决定是否需要调整默认栈大小。
栈保护区
int pthread_attr_getguardsize(const pthread_attr_t *restrict attr,size_t *restrict guardsize);
int pthread_attr_setguardsize(pthread_attr_t *attr,size_t guardsize);
出于以下两个原因,为应用程序提供了 guardsize 属性:
-
溢出保护可能会导致系统资源浪费。如果应用程序创建大量线程,并且已知这些线程永远不会溢出其栈,则可以关闭溢出保护区。通过关闭溢出保护区,可以节省系统资源。
-
线程在栈上分配大型数据结构时,可能需要较大的溢出保护区来检测栈溢出。
guardsize 参数提供了对栈指针溢出的保护。如果创建线程的栈时使用了保护功能,则实现会在栈的溢出端分配额外内存。此额外内存的作用与缓冲区一样,可以防止栈指针的栈溢出。如果应用程序溢出到此缓冲区中,这个错误可能会导致 SIGSEGV 信号被发送给该线程。
如果 guardsize 为零,则不会为线程提供溢出保护区。如果 guardsize 大于零,则会为每个使用 attr 创建的线程提供大小至少为 guardsize 字节的溢出保护区。缺省情况下,线程具有实现定义的非零溢出保护区。
允许合乎惯例的实现,将 guardsize 的值向上舍入为可配置的系统变量 PAGESIZE 的倍数。
调度属性
属性名 | 接口 | 描述 |
---|---|---|
调度继承属性 | pthread_attr_getinheritsched, pthread_attr_setinheritsched | 是否继承调度属性的设置 |
调度优先级属性 | pthread_attr_getschedparam, pthread_attr_setschedparam | 调度优先级参数的设置 |
调度策略属性 | pthread_attr_getschedpolicy, pthread_attr_setschedpolicy | 调度策略属性的设置 |
调度资源的范围 | pthread_attr_getscope, pthread_attr_setscope | 设置调度资源的范围 |
CPU 亲和性 | pthread_attr_getaffinity_np,pthread_attr_setaffinity_np | 设置线程运行时绑定的CPU core |
线程调度属性主要有以下几种:
- 继承属性
- 调度参数属性
- 调度策略属性
- CPU亲和性属性
继承属性
int pthread_attr_setinheritsched(pthread_attr_t *attr,int inheritsched);
int pthread_attr_getinheritsched(pthread_attr_t *attr,int *inheritsched);
- inherit 值为
PTHREAD_INHERIT_SCHED
表示新建的线程将继承创建者线程中定义的调度策略, 将忽略在 pthread_create() 调用中定义的所有调度属性。 - 如果使用缺省值
PTHREAD_EXPLICIT_SCHED
,则将使用 pthread_create() 调用中的属性。
调度策略属性
int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy);
int pthread_attr_getschedpolicy(pthread_attr_t *attr, int *policy);
这里的策略支持三种取值:
当policy 取值为以下:
- SCHED_FIFO, 先来先服务;
- SCHED_RR, 时间片轮转;
- SCHED_OTHER, 普通策略;
前两种是realtime,实时系统的调度策略,一般不会使用,它们两个支持优先级的设置,范围是1-99;
第三种是用户线程默认的策略类型,在内核中的命名是SCHED_NORMAL
, 不支持优先级设置,必须为0;
当然在SCHED_OTHER
策略下的各用户线程之间可以通过调整nice值,进行优先级调整,它的范围为-20 - 19之间,越小优先级越高。
优先级属性
int pthread_attr_setschedparam(pthread_attr_t *attr,const struct sched_param *param);
int pthread_attr_getschedparam(pthread_attr_t *attr,struct sched_param *param);
调度参数在结构sched_param
中定义,仅支持优先级参数设定。
优先级参数仅在支持的调度策略下设置才有效,在SCHED_OTHER
, SCHED_IDLE
, SCHED_BATCH
这三种策略下,优先级必须设置为0;
在SCHED_FIFO
, SCHED_RR
这两种实时调度策略下,优先级范围为1-99,数字越大优先级越高;
新创建的线程以此优先级运行, 简单示例代码如下:
pthread_attr_t tattr;
int newprio;
sched_param param;/* set the priority; others are unchanged */
param.sched_priority = 10;/* set the new scheduling param */
ret = pthread_attr_setschedparam (&tattr, ¶m);
调度资源范围属性
int pthread_attr_setscope(pthread_attr_t *attr, int contentionscope);
int pthread_attr_getscope(const pthread_attr_t *attr, int *contentionscope);
contentionscope的取值如下:
- PTHREAD_SCOPE_SYSTEM, 线程在抢占资源,与它竞争的线程是系统中的所有线程;
- PTHREAD_SCOPE_PROCESS, 线程在抢占资源时,与它竞争的线程是本进程创建的线程,优先级依赖与策略和优先级设定;
CPU亲和性属性
int pthread_attr_setaffinity_np(pthread_attr_t *attr,size_t cpusetsize, const cpu_set_t *cpuset);
int pthread_attr_getaffinity_np(pthread_attr_t *attr, size_t cpusetsize, cpu_set_t *cpuset);
参数说明
- cpusetsize, 是第三个参数的size, 也就是sizeof(cpu_set_t);
- cpuset, 指定CPU core的掩码,使用
CPU_ZERO(&set);
和CPU_SET(numCpu, &set);
两个宏来设定,numCpu指定绑定的core或thread编号,是整型数字;
参看机制的CPU 数量和core数量
[senllang@hatch example_03]$ lscpu | egrep -i 'core.*:|socket'
Thread(s) per core: 2
Core(s) per socket: 8
Socket(s): 1
这里有一个CPU,包含8个core,每个core可以有两个线程,那就是可以有16个掩码值,设置时编号从0-15;
有时CPU会采用NUMA架构,那么相关线程需要设置到同一个Node的CPU编号下。
分离属性
int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
int pthread_attr_getdetachstate(pthread_attr_t *attr, int *detachstate);
detachstate的取值如下:
- PTHREAD_CREATE_DETACHED, 创建分离状态的线程,此时不用关注线程退出时的资源回收;
- PTHREAD_CREATE_JOINABLE, 创建可连接状态的线程,线程退出时,需要使用pthread_join对线程资源回收;默认参数就是可连接状态的线程。
如果线程以PTHREAD_CREATE_JOINABLE创建后,没有时机调用pthread_join时,还可以调用pthread_detach 函数,将指定线程置为分离状态,这样系统会自动回收线程资源。
如果线程以PTHREAD_CREATE_JOINABLE创建后,没有调用pthread_join,会造成一定的内存泄漏,这里一定要注意。
信号属性
#define _GNU_SOURCE /* See feature_test_macros(7) */
#include <pthread.h>int pthread_attr_setsigmask_np(pthread_attr_t *attr,const sigset_t *sigmask);
int pthread_attr_getsigmask_np(const pthread_attr_t *attr,sigset_t *sigmask);
设置线程级别的信号掩码,也就是那些信号会被阻塞。
sigset_t 类型的操作,需要使用一组信号掩码操作函数
- int sigemptyset (sigset_t *set) ,清空信号掩码变量
- int sigfillset (sigset_t *set) , 填充所有信号掩码
- int sigaddset (sigset_t *set, int signum) ,将某个信号添加到掩码中
- int sigdelset (sigset_t *set, int signum) ,将某个信号从掩码中移除
- int sigismember (const sigset_t *set, int signum), 检测某个信号是否在掩码中
默认属性
#define _GNU_SOURCE /* See feature_test_macros(7) */
#include <pthread.h>int pthread_getattr_default_np(pthread_attr_t *attr);
int pthread_setattr_default_np(pthread_attr_t *attr);int pthread_getattr_np(pthread_t thread, pthread_attr_t *attr);
前两个函数是将线程属性设置为默认值,也就是创建线程时,将线程属性设置为NULL,这两者是等价的。
第三个函数是获取指定线程的属性,可以在线程运行过程中获取线程属性。
总结
本文主要分享了线程属性相关的接口,以及部分属性的含义,如何正确使用;在应用编程时,大多数情况下都会采用多线程并发的架构,线程属性的正确使用,能够帮助我们有提高CPU的利用效率,同时在使用过程中避够资源泄漏也非常关键。
在gitCode上分享了工程hatchCode,会不断增加多线程并发的案例代码,请大家关注保留。
结尾
非常感谢大家的支持,在浏览的同时别忘了留下您宝贵的评论,如果觉得值得鼓励,请点赞,收藏,我会更加努力!
作者邮箱:study@senllang.onaliyun.com
如有错误或者疏漏欢迎指出,互相学习。
相关文章:
【linux 多线程并发】线程属性设置与查看,绑定CPU,线程分离与可连接,避够多线程下的内存泄漏
线程属性设置 专栏内容: 参天引擎内核架构 本专栏一起来聊聊参天引擎内核架构,以及如何实现多机的数据库节点的多读多写,与传统主备,MPP的区别,技术难点的分析,数据元数据同步,多主节点的情况…...

70.乐理基础-打拍子-三连音
上一个内容:69.乐理基础-打拍子-大切分与变体-CSDN博客 62-66是总拍数为一拍的节奏型,一共有七个,68-69是两拍的节奏型。 三连音说明: 1.三连音的总拍数可以是一拍、两拍、四拍。。。。 2.打拍子比较难,或许需要用V字…...

100天精通Python(实用脚本篇)——第111天:批量将PDF转Word文档(附上脚本代码)
文章目录 专栏导读1. 将PDF转Word文档需求2. 模块安装3. 模块介绍4. 注意事项5. 完整代码实现6. 运行结果书籍推荐 专栏导读 🔥🔥本文已收录于《100天精通Python从入门到就业》:本专栏专门针对零基础和需要进阶提升的同学所准备的一套完整教…...

如何在 NAS 上安装 ONLYOFFICE 文档?
文章作者:ajun 导览 ONLYOFFICE 文档 是一款开源办公套件,其是包含文本文档、电子表格、演示文稿、表单、PDF 查看器和转换工具的协作性编辑工具。它高度兼容微软 Office 格式,包括 .docx、.xlsx 、.pptx 、pdf等文件格式,并支持…...

Baumer工业相机堡盟工业相机如何通过NEOAPI SDK设置相机的图像剪切(ROI)功能(C++)
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK设置相机的图像剪切(ROI)功能(C) Baumer工业相机Baumer工业相机的图像剪切(ROI)功能的技术背景CameraExplorer如何使用图像剪切(ROI)功…...
从 WasmEdge 运行环境读写 Rust Wasm 应用的时序数据
WebAssembly (Wasm) 正在成为一个广受欢迎的编译目标,帮助开发者构建可迁移平台的应用。最近 Greptime 和 WasmEdge 协作,支持了在 WasmEdge 平台上的 Wasm 应用通过 MySQL 协议读写 GreptimeDB 中的时序数据。 什么是 WebAssembly WebAssembly 是一种…...

算法训练营Day34(贪心算法)
1005.K次取反后最大化的数组和 1005. K 次取反后最大化的数组和 - 力扣(LeetCode) 秒了 class Solution {public int largestSumAfterKNegations(int[] nums, int k) {Arrays.sort(nums);// -4 -3 -2 -1 5//-2 -2 0 2 5int last -1;for(int i 0;i<…...

uniapp:全局消息是推送,实现app在线更新,WebSocket,apk上传
全局消息是推送,实现app在线更新,WebSocket 1.在main.js中定义全局的WebSocket2.java后端建立和发送WebSocket3.通知所有用户更新 背景: 开发人员开发后app后打包成.apk文件,上传后通知厂区在线用户更新app。 那么没在线的怎么办&…...

ARM1.2作业
实现数码管不同位显示不同的数字 spi.h #ifndef __SPI_H__ #define __SPI_H__ #include "stm32mp1xx_gpio.h" #include "stm32mp1xx_rcc.h"//MOSI对应的引脚输入高低电平的信号PE14 #define MOSI_OUTPUT_H() do{GPIOE->ODR | (0x1 << 14);}whi…...
【算法专题】递归算法
递归 递归1. 汉诺塔问题2. 合并两个有序链表3. 反转链表4. 两两交换链表中的节点5. Pow(x, n) --- 快速幂 递归 在解决⼀个规模为 n 的问题时,如果满足以下条件,我们可以使用递归来解决: 问题可以被划分为规模更小的子问题,并且…...
不停止业务的情况下优化 Elasticsearch Reindex
在使用 Elasticsearch 时,我们总有需要修改索引映射的时候,这时我们只能进行 _reindex。事实上,这是一个相当昂贵的操作,因为根据数据量和分片数量,完整复制一个索引可能需要几个小时。 花费的时间不是大问题,但更严重的是,它会影响生产环境的性能甚至功能。 相信大家…...
PB 按Excel动态创建对应字段
/* > Function: w_cwjk_xhyy.wf_dw_init >-------------------------------------------------------------------- > 描述: 按excel表格列名,创建对应字段,用于部分接口对应字段导出文件 >-------------------------------------------------------------------- …...

数据结构——红黑树 and B-树
红黑树 根据平衡条件第4、5两点 最短路径,都是黑色 最长路径,红黑相间 最长是最短的两倍 B-树...
Android中线程间的通信-Handler
Handler机制在Android中主要用于线程间的通信,特别是处理从子线程向主线程(UI线程)传递消息和更新界面。 Handler中的四个关键对象及其作用: Message: Message 是在线程间传递的数据载体,它包含了需要处理…...

Spring Boot Admin健康检查引起的Spring Boot服务假死
问题现象 最近在spring boot项目中引入了 spring-boot-starter-actuator 后,测试环境开始出现服务假死的现象, 且这个问题十分怪异,只在多个微服务中的简称A的这个服务中出现,其他服务都没有出现这个问题, 之所以说…...

java企业人事信息管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目
一、源码特点 java Web企业人事信息管理系统是一套完善的java web信息管理系统,对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发环境 为TOMCAT7.0,Myeclipse8.5开发,数据库为M…...
如何通过 useMemo 和 useCallback 提升你的 React 应用性能
背景 在 React 中,useMemo 和 useCallback 这两个 hook 是我们优化应用性能的有力工具。它们会返回 memoized 版本的值或函数,只在依赖项发生变化时才进行重新计算或定义。 Hook 介绍 useMemo useMemo 的作用是返回一个 memoized 值,它接…...

ArkTS - @Prop、@Link
一、作用 Prop 装饰器 和Link装饰器都是父组件向子组件传递参数,子组件接收父组件参数的时候用的,变量前边需要加上Prop或者Link装饰器即可。(跟前端vue中父组件向子组件传递参数类似) // 子组件 Component struct SonCom {Prop…...

Python中matplotlib库的使用1
1 matplotlib库简介 matplotlib是一个数学绘图库,可以将数据通过图形的方式显示出来,也就是数据可视化。 2 matplotlib库的安装 2.1 打开cmd窗口 点击键盘的“Win”“R”键,在弹出的“运行”对话框的“打开”栏中输入“cmd”,…...
位乘积计数-蓝桥
题目链接:1.位乘积计数 - 蓝桥云课 (lanqiao.cn) 解题思路:10的5次数量级暴力居然过了,看来测试样例很水,直接1遍历到n,再用一个循环判断每位数相乘乘机是否等于m即可。 下面是c代码: #include <iost…...

eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)
说明: 想象一下,你正在用eNSP搭建一个虚拟的网络世界,里面有虚拟的路由器、交换机、电脑(PC)等等。这些设备都在你的电脑里面“运行”,它们之间可以互相通信,就像一个封闭的小王国。 但是&#…...
web vue 项目 Docker化部署
Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage):…...
【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密
在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...

Nuxt.js 中的路由配置详解
Nuxt.js 通过其内置的路由系统简化了应用的路由配置,使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...

让AI看见世界:MCP协议与服务器的工作原理
让AI看见世界:MCP协议与服务器的工作原理 MCP(Model Context Protocol)是一种创新的通信协议,旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天,MCP正成为连接AI与现实世界的重要桥梁。…...

MFC 抛体运动模拟:常见问题解决与界面美化
在 MFC 中开发抛体运动模拟程序时,我们常遇到 轨迹残留、无效刷新、视觉单调、物理逻辑瑕疵 等问题。本文将针对这些痛点,详细解析原因并提供解决方案,同时兼顾界面美化,让模拟效果更专业、更高效。 问题一:历史轨迹与小球残影残留 现象 小球运动后,历史位置的 “残影”…...

C# 表达式和运算符(求值顺序)
求值顺序 表达式可以由许多嵌套的子表达式构成。子表达式的求值顺序可以使表达式的最终值发生 变化。 例如,已知表达式3*52,依照子表达式的求值顺序,有两种可能的结果,如图9-3所示。 如果乘法先执行,结果是17。如果5…...

基于Java+VUE+MariaDB实现(Web)仿小米商城
仿小米商城 环境安装 nodejs maven JDK11 运行 mvn clean install -DskipTestscd adminmvn spring-boot:runcd ../webmvn spring-boot:runcd ../xiaomi-store-admin-vuenpm installnpm run servecd ../xiaomi-store-vuenpm installnpm run serve 注意:运行前…...
Kubernetes 网络模型深度解析:Pod IP 与 Service 的负载均衡机制,Service到底是什么?
Pod IP 的本质与特性 Pod IP 的定位 纯端点地址:Pod IP 是分配给 Pod 网络命名空间的真实 IP 地址(如 10.244.1.2)无特殊名称:在 Kubernetes 中,它通常被称为 “Pod IP” 或 “容器 IP”生命周期:与 Pod …...

nnUNet V2修改网络——暴力替换网络为UNet++
更换前,要用nnUNet V2跑通所用数据集,证明nnUNet V2、数据集、运行环境等没有问题 阅读nnU-Net V2 的 U-Net结构,初步了解要修改的网络,知己知彼,修改起来才能游刃有余。 U-Net存在两个局限,一是网络的最佳深度因应用场景而异,这取决于任务的难度和可用于训练的标注数…...