当前位置: 首页 > news >正文

【操作系统(Linux)】——多线程对共享变量访问的同步与互斥

一、多线程对共享变量的非互斥访问

我们将要做的:构造多线程共享变量竞争的案例,并分析现象发生的原因,进而思考解决方式。

案例源代码:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <string.h>int num=30,count=10;void *sub1(void *arg) {int i = 0,tmp;for (; i <count; i++){tmp=num-1;usleep(13);num=tmp;printf("线程1 num减1后值为: %d\n",num);}return ((void *)0);
}
void *sub2(void *arg){int i=0,tmp;for(;i<count;i++){tmp=num-1;usleep(31);num=tmp;printf("线程2 num减1后值为: %d\n",num);}return ((void *)0);
}
int main(int argc, char** argv) {pthread_t tid1,tid2; // 两个子线程的idint err,i=0,tmp;void *tret; // 线程返回值err=pthread_create(&tid1,NULL,sub1,NULL);if(err!=0){printf("pthread_create error:%s\n",strerror(err));exit(-1);}err=pthread_create(&tid2,NULL,sub2,NULL);if(err!=0){printf("pthread_create error:%s\n",strerror(err));exit(-1);}for(;i<count;i++){tmp=num-1;usleep(5);num=tmp;printf("main num减1后值为: %d\n",num);}printf("两个线程运行结束\n");err=pthread_join(tid1,&tret);if(err!=0){printf("can not join with thread1:%s\n",strerror(err));exit(-1);}printf("thread 1 exit code %d\n",(int)tret);err=pthread_join(tid2,&tret);if(err!=0){printf("can not join with thread1:%s\n",strerror(err));exit(-1);}printf("thread 2 exit code %d\n",(int)tret);return 0;
}

🧠 1. 程序功能概述

创建了两个线程 sub1sub2,以及主线程三者共同对一个全局变量 num 执行减 1 操作,共减去 count * 3 = 30 次。

初始值:

int num = 30, count = 10;

所以理论上最终 num == 0,但实际上并不一定!


⚠️ 2. 存在的核心问题:数据竞争(Race Condition)

❗ 对 num-- 是分三步执行的:
tmp = num - 1;
usleep(x);
num = tmp;

这个过程不是原子操作,多个线程可能“交叉”访问这个变量,造成竞态条件(Race Condition)

中间插入 usleep() 只是为了放大并发写入带来的冲突概率,模拟真实环境下的并发问题。

举例说明:

假设此时 num = 10,两个线程同时读到:

线程1:tmp1 = 10 - 1 = 9,睡眠
线程2:tmp2 = 10 - 1 = 9,睡眠

然后:

线程1醒来执行 num = 9
线程2醒来执行 num = 9 (覆盖了线程1的操作)

🔴 这样 num 实际只减少了一次,而我们期望它减少两次(一个线程分别减少一次)!


🔍 3. 运行效果举例(输出可能类似):

线程1 num减1后值为: 29
线程2 num减1后值为: 28
main num减1后值为: 27
线程1 num减1后值为: 27  ←❗ 重复了
main num减1后值为: 26
线程2 num减1后值为: 26  ←❗ 再次重复

最终 num 的值可能 不是 0,甚至是更高。原因就是上面说的:很多次减法操作失效了。


✅4. 如何解决?使用线程同步机制:互斥锁 pthread_mutex_t

例如,添加全局互斥锁

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

将每个对 num 的访问部分用锁保护:

pthread_mutex_lock(&lock);
tmp = num - 1;
usleep(13); // 保留你原来的模拟处理
num = tmp;
pthread_mutex_unlock(&lock);

🔒 这样确保每次只有一个线程在访问和修改 num


🛠️ 5. 修改后关键片段示例(以 sub1 为例)

void *sub1(void *arg) {int i = 0, tmp;for (; i < count; i++) {pthread_mutex_lock(&lock);tmp = num - 1;usleep(13);num = tmp;printf("线程1 num减1后值为: %d\n", num);pthread_mutex_unlock(&lock);}return ((void *)0);
}

主线程、sub2 中也要加锁。


🔚 6. 总结

问题说明
数据竞争多线程访问全局变量未加锁
后果num 最终值不确定,减法丢失
解决使用 pthread_mutex 互斥锁
调试建议加 -fsanitize=thread 或使用 valgrind --tool=helgrind 检查

二、并发线程同步与互斥

本次案例是在前一个案例「多线程对共享变量的非互斥访问」的基础上进行了修复和优化,引入了 pthread_mutex 互斥锁机制,实现了 多线程对共享变量的互斥访问控制,有效解决了数据竞争问题。

案例源代码:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <string.h>
int num=30, count=10;
pthread_mutex_t mylock=PTHREAD_MUTEX_INITIALIZER;
void *sub1(void *arg) {int i = 0,tmp;for (; i<count; i++){pthread_mutex_lock(&mylock);   // 上锁		tmp=num-1;usleep(13);num=tmp;pthread_mutex_unlock(&mylock); // 解锁	printf("线程1  第「%d」次num减1后值为: %d\n",i+1,num);}return ((void *)0);
}
void *sub2(void *arg){int i=0,tmp;for(;i<count;i++){pthread_mutex_lock(&mylock); // 上锁tmp=num-1;usleep(31);num=tmp;pthread_mutex_unlock(&mylock); // 解锁printf("线程2  第「%d」次num减1后值为: %d\n",i+1,num);}return ((void *)0);
}
int main(int argc, char** argv) {pthread_t tid1,tid2;int err,i=0,tmp;void *tret; // 线程返回值err=pthread_create(&tid1,NULL,sub1,NULL);if(err!=0){printf("pthread_create error:%s\n",strerror(err));exit(-1);}err=pthread_create(&tid2,NULL,sub2,NULL);if(err!=0){printf("pthread_create error:%s\n",strerror(err));exit(-1);}for(;i<count;i++){pthread_mutex_lock(&mylock); // 主线程上锁tmp=num-1;usleep(5); // num=tmp;		pthread_mutex_unlock(&mylock); // 主线程释放锁printf("主线程 第「%d」次num减1后值为: %d\n",i+1,num);}printf("两个线程运行结束\n");err=pthread_join(tid1,&tret);if(err!=0){printf("can not join with thread1:%s\n",strerror(err));exit(-1);}printf("thread 1 exit code %d\n",(int)tret);err=pthread_join(tid2,&tret);if(err!=0){printf("can not join with thread1:%s\n",strerror(err));exit(-1);}printf("thread 2 exit code %d\n",(int)tret);return 0;
}

下面从结构和功能两个维度逐段讲解这段代码。


✅ 1. 程序功能概述

多线程同时对一个共享变量 num 进行减 1 操作,为避免多个线程同时访问导致的数据错误,使用 互斥锁 pthread_mutex_t 实现同步,确保线程间的安全访问。


🔧 2. 头文件说明

#include <stdio.h>      // printf()
#include <stdlib.h>     // exit()
#include <pthread.h>    // pthread_create, pthread_join, pthread_mutex_*
#include <unistd.h>     // usleep()
#include <string.h>     // strerror()

✅ 上述头文件提供了线程创建、同步、休眠和错误信息处理等功能。


🔐 3. 全局变量及互斥锁

int num=30, count=10;
pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER;
  • num: 被所有线程共享的变量,初始为 30。
  • count: 每个线程循环次数。
  • mylock: 全局互斥锁,用于防止多个线程同时修改 num

🧵 4. 线程函数 sub1 和 sub2

🔹 sub1 函数
void *sub1(void *arg) {int i = 0, tmp;for (; i < count; i++) {pthread_mutex_lock(&mylock);      // 上锁tmp = num - 1;usleep(13);                       // 模拟计算耗时num = tmp;pthread_mutex_unlock(&mylock);    // 解锁printf("线程1 第【%d】num减1后值为: %d\n", i, num);}return ((void *)0);
}
🔹 sub2 函数
void *sub2(void *arg) {int i = 0, tmp;for (; i < count; i++) {pthread_mutex_lock(&mylock);tmp = num - 1;usleep(31);num = tmp;pthread_mutex_unlock(&mylock);printf("线程2 第【%d】num减1后值为: %d\n", i, num);}return ((void *)0);
}

🟡 共同点:

  • 都对共享变量 num 执行减 1 操作。
  • 每次操作前后都加了互斥锁,保证了对 num 的访问是互斥的。

🟡 不同点:

  • 睡眠时间不同,用于模拟线程调度差异,放大并发现象。

👑 5. 主线程 main 函数

1️⃣ 创建线程
pthread_create(&tid1, NULL, sub1, NULL);
pthread_create(&tid2, NULL, sub2, NULL);
  • 启动两个子线程 sub1sub2,它们会与主线程并发执行。

2️⃣ 主线程也参与对 num 的操作
for (; i < count; i++) {pthread_mutex_lock(&mylock);tmp = num - 1;usleep(5);num = tmp;pthread_mutex_unlock(&mylock);printf("main 第【%d】num减1后值为: %d\n", i, num);
}

💡 主线程和子线程一样,每次操作都加锁保护,保证不会同时操作 num,从而避免数据冲突


3️⃣ 等待线程结束并获取退出状态
pthread_join(tid1, &tret);
pthread_join(tid2, &tret);
  • 使用 pthread_join() 等待线程结束。
  • 线程的返回值是 NULL(即 return ((void*)0)),打印时结果是 0

🧪 6. 运行效果示例(输出节选)

主线程 第「1」次num减1后值为: 29
主线程 第「2」次num减1后值为: 28
主线程 第「3」次num减1后值为: 27
线程1  第「1」次num减1后值为: 26
线程1  第「2」次num减1后值为: 25
...

最终:

两个线程运行结束
thread 1 exit code 0
thread 2 exit code 0

🔒 7. 为什么这次没有竞态条件?

因为你加入了 pthread_mutex_lock()pthread_mutex_unlock() 对每一次对 num 的读-改-写操作进行了加锁保护,确保每次修改都是互斥的、完整的


📌 八、总结

项目说明
多线程创建使用 pthread_create 创建两个线程
共享资源所有线程和主线程共享变量 num
数据保护使用 pthread_mutex 实现访问同步,防止竞态
同步结束使用 pthread_join 等待子线程结束
延时模拟使用 usleep() 模拟并发中的调度差异

相关文章:

【操作系统(Linux)】——多线程对共享变量访问的同步与互斥

一、多线程对共享变量的非互斥访问 我们将要做的&#xff1a;构造多线程共享变量竞争的案例&#xff0c;并分析现象发生的原因&#xff0c;进而思考解决方式。 案例源代码&#xff1a; #include <stdio.h> #include <stdlib.h> #include <pthread.h> #inc…...

deeplabv3+街景图片语义分割,无需训练模型,看不懂也没有影响,直接使用,cityscapes数据集_16

目录 1、下载链接1.1、CSDN链接&#xff0c;含权重文件直接使用&#xff0c;建议直接下这个&#xff0c;还不限速。1.2 Github链接&#xff1a; 2、下载代码&#xff0c;下载预训练好的权重3、预测代码4、像素提取&#xff0c;或者说类别提取5、文档部分内容截图6、其他数据处理…...

[前端]从人体结构看网页三要素:HTML、CSS 与 JavaScript

目录 一、HTML:网页的 “骨架” 二、CSS:网页的 “血肉” 三、JavaScript:网页的 “神经系统” 四、三者协同构建精彩网页 在互联网的浩瀚海洋中,网页是我们与世界交互的重要窗口。一个精彩的网页背后,离不开 HTML、CSS 和 JavaScript 这三位 “幕后英雄”。有趣的是,…...

【Leetcode】3375. 使数组的值全部为 K 的最少操作次数

文章目录 题目思路代码复杂度分析时间复杂度空间复杂度 结果总结 题目 题目链接&#x1f517; 给你一个整数数组 nums 和一个整数 k 。 如果一个数组中所有 严格大于 h 的整数值都 相等 &#xff0c;那么我们称整数 h 是 合法的 。 比方说&#xff0c;如果 nums [10, 8, 10…...

封装uniapp request promise化

uniapp request 封装 一、 封装方法1. 使用 promis 封装 request2. 封装 api 在 api.js3.在要请求的页面 调用 api 一、 封装方法 1. 使用 promis 封装 request const BASE_URL 你的url接口 //比如 http://198.12.3.3/pzexport function request(config {}){let {url,dat…...

架构演进成熟度校验体系构建

架构演进成熟度校验体系构建 ——基于电商价格服务Checklist的图形化实践指南 一、成熟度校验全景视图 #mermaid-svg-tXchQ6nY7QzNUrL1 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-tXchQ6nY7QzNUrL1 .error-ico…...

Llama 4全面评测:官方数据亮眼,社区测试显不足之处

引言 2025年4月&#xff0c;Meta正式发布了全新的Llama 4系列模型&#xff0c;这标志着Llama生态系统进入了一个全新的时代。Llama 4不仅是Meta首个原生多模态模型&#xff0c;还采用了混合专家(MoE)架构&#xff0c;并提供了前所未有的上下文长度支持。本文将详细介绍Llama 4…...

kotlin 多个fragment beginTransaction容器添加使用

在Kotlin中如何使用Fragment的beginTransaction来添加多个Fragment到容器中。我需要先回顾一下Fragment的基本用法&#xff0c;然后考虑多个Fragment的情况。 FragmentTransaction的beginTransaction是用来开启一个事务&#xff0c;然后添加、替换或移除Fragment。通常&#x…...

(PTA) L2-011-L2-015

L2-012 关于堆的判断 由于没有得到AC代码&#xff08;1&#xff0c;3测试点错误&#xff09;,这里先不做展示&#xff0c;等后续复盘的时候进行补充。 L2-011 玩转二叉树 给定一棵二叉树的中序遍历和前序遍历&#xff0c;请你先将树做个镜面反转&#xff0c;再输出反转后的层序…...

管理Linux服务器的用户和组

用户/组 命令符会展示当前用户名和主机名 创建用户&#xff0c;同时创建同名组 useradd 用户名 设置密码 passwd 用户名 切换用户登录 su 用户名 删除用户 userdel -r 用户名 记录用户信息的文件 /etc/passwd 记录密码&#xff08;密文&#xff09;信息的文件 /etc/sh…...

奇安信驻场面试题

《网安面试指南》https://mp.weixin.qq.com/s/RIVYDmxI9g_TgGrpbdDKtA?token1860256701&langzh_CN 5000篇网安资料库https://mp.weixin.qq.com/s?__bizMzkwNjY1Mzc0Nw&mid2247486065&idx2&snb30ade8200e842743339d428f414475e&chksmc0e4732df793fa3bf39…...

Testbench设计

一、几个名词&#xff1a; 被仿真的文件叫DUT&#xff08;Design under Test&#xff09; 编写Testbench的目的 验证设计有没问题。 怎么写Testbench&#xff1f; 四、Teshbench各个部分的写法&#xff1a; 外部信号就是外面连接的信号。...

使用IPython有哪些好处?

这里总结了50个使用IPython的好处&#xff0c;大大提升开发效率&#xff01; 什么是IPython&#xff1f;可能很多人已经在用&#xff0c;却不知道它到底是什么。 根据维基百科的解释&#xff1a; IPython是一种基于Python的交互式解释器&#xff0c;提供了强大的编辑和交互功能…...

加油站小程序实战教程10开通会员

目录 1 修改用户登录逻辑2 创建变量3 调用API总结 我们上一篇搭建了开通会员的界面&#xff0c;有了界面的时候就需要加入一些逻辑来控制界面显示。我们的逻辑是当用户打开我的页面的时候&#xff0c;在页面加载完毕后调用API看用户是否已经开通会员了&#xff0c;如果未开通就…...

NO.84十六届蓝桥杯备战|动态规划-路径类DP|矩阵的最小路径和|迷雾森林|过河卒|方格取数(C++)

路径类dp是线性dp的⼀种&#xff0c;它是在⼀个nm的矩阵中设置⼀个⾏⾛规则&#xff0c;研究从起点⾛到终点的⽅案数、最⼩路径和或者最⼤路径和等等的问题 矩阵的最小路径和_牛客题霸_牛客网 状态表⽰&#xff1a; dp[i][j]表⽰&#xff1a;到达[i, j]位置处&#xff0c;最⼩…...

WHAT - React 技术栈常用库/工具

目录 基础类状态管理路由管理UI 组件库开发工具 / 辅助库测试相关表单和数据展示其它实用类代码重构应用迁移&#xff1a;PWA代码组织与架构建议&#xff08;选项&#xff09; 下面是一个 React 技术栈常用库/工具清单&#xff0c;按不同分类整理&#xff0c;涵盖开发、状态管理…...

FreeSWITCH的SIP配置

确认 FreeSWITCH 的 SIP 配置 FreeSWITCH 的 SIP 配置文件通常位于 /usr/local/freeswitch/conf/sip_profiles 目录下。默认情况下&#xff0c;FreeSWITCH 使用 internal.xml 和 external.xml 作为 SIP 配置文件。 查看 internal.xml 配置 编辑 /usr/local/freeswitch/conf/sip…...

Spark核心知识总结

一、Spark运行架构 &#xff08;一&#xff09;整体结构 Spark框架采用标准master - slave结构&#xff0c;Driver为master管理作业任务调度&#xff0c;Executor为slave负责实际执行任务。 &#xff08;二&#xff09;核心组件 1. Driver&#xff1a;执行Spark任务的main方法&…...

第1节:计算机视觉发展简史

计算机视觉与图像分类概述&#xff1a;计算机视觉发展简史 计算机视觉&#xff08;Computer Vision&#xff09;作为人工智能领域的重要分支&#xff0c;是一门研究如何使机器"看"的科学&#xff0c;更具体地说&#xff0c;是指用摄影机和计算机代替人眼对目标进行识…...

2D 与 3D 连线效果全解析 | 从平面到立体

HT 是一个灵活多变的前端组件库&#xff0c;具备丰富的功能和效果&#xff0c;满足多种开发需求。让我们将其效果化整为零&#xff0c;逐一拆解具体案例&#xff0c;帮助你更好地理解其实现方案。 在此篇文章中&#xff0c;让我们一起深入探讨 2D 与 3D 的连线效果是如何实现的…...

Django Cookies 实际项目示例

Django Cookies 实际项目示例 推荐超级课程: 本地离线DeepSeek AI方案部署实战教程【完全版】Docker快速入门到精通Kubernetes入门到大师通关课AWS云服务快速入门实战目录 Django Cookies 实际项目示例介绍什么是 Django Cookies?为什么要关心 Django Cookies?Django Cookie…...

【问题排查】SQLite安装失败

启动 Django 自带的开发服务器 python manage.py runserver出现如下报错&#xff1a; [rootiZ2zedudtf2cwzi9argky2Z myproject]# python manage.py runserver Watching for file changes with StatReloader Performing system checks...System check identified no issues (…...

stream流Collectors.toMap(),key值重复问题

文章目录 一、问题二、问题示例三、原因四、解决方法4.1、方案一 一、问题 发现Collectors.toMap的一个坑&#xff0c;若key值重复的时候会抛异常。如&#xff1a; IllegalStateException: Duplicate key 男 二、问题示例 报错示例如下&#xff1a; import lombok.AllArgsC…...

STM32(基于标准库)

参考博客&#xff1a;江科大STM32笔记 Stm32外设 一、GPIO 基础 GPIO位结构 I/O引脚的保护二极管是对输入电压进行限幅的上面的二极管接VDD, 3.3V,下面接VSS, 0V&#xff0c;当输入电压 >3.3V 那上方这个二极管就会导通&#xff0c;输入电压产生的电流就会大部分充入VD…...

OpenStack Yoga版安装笔记(十八)Self-service networks配置笔记

1、官方文档 在OpenStack官方安装文档中&#xff0c;提供了两个网络配置选项&#xff1a; Option1&#xff1a;Provider networksOption2&#xff1a;Self-service networks 这两个选项并不冲突&#xff0c;可以在OpenStack环境中同时配置。 在《OpenStack Yoga版安装笔记&…...

2025年黑龙江建筑安全员 C3 证考试题库练习题

黑龙江建筑安全员 C3 证考试题库练习题 1、消防控制室是设有火灾自动报警设备和消防设施控制设备&#xff0c;用于接收、显示、处理&#xff08; &#xff09;&#xff0c;控制相关消防设施的专门处所2。 A. 安全信息 B. 设备信息 C. 通讯信号 D. 火灾报警信号 答案&…...

JavaScript数据结构-Map的使用

在 JavaScript 中&#xff0c;Map 是 ES6 引入的一种新的数据结构&#xff0c;它类似于对象&#xff0c;也是键值对的集合&#xff0c;但 Map 的键可以是任意类型的值&#xff08;对象、函数、基本类型等&#xff09;&#xff0c;而传统对象的键只能是字符串或 Symbol&#xff…...

LeetCode面试经典150题

目录 力扣80. 删除有序数组中的重复项 II 代码解析 力扣274. H 指数 代码解析 力扣151. 反转字符串中的单词 解析代码 力扣12. 整数转罗马数字 解析代码 力扣28. 找出字符串中第一个匹配项的下标 解析代码1&#xff08;暴力模拟&#xff09; 解析代码2&#xff08;K…...

mysql之等值连接8个实例

以下实例以常见的业务场景为例&#xff0c;使用 MySQL 语法&#xff0c;假设存在员工表&#xff08;employees&#xff09;、部门表&#xff08;departments&#xff09;、订单表&#xff08;orders&#xff09;、客户表&#xff08;customers&#xff09;等&#xff0c;来展示…...

C基础笔记_指针专题

一:C 和 C 偏爱使用指针的原因 1. 通过指针可以直接操作内存 C 和 C 是系统级编程语言&#xff0c;它们的设计目标之一是允许开发者直接与硬件交互并高效地管理资源。 指针的本质&#xff1a;指针本质上是一个存储内存地址的变量&#xff0c;它让程序员可以直接访问和操作内…...

GPT-SoVITS Windows 配置与推理笔记(自用)

GPT-SoVITS Windows 配置与推理笔记&#xff08;自用&#xff09; 这是给自己留的备份&#xff0c;方便下次查。Windows 端配置和推理为主&#xff0c;代码为核心&#xff0c;直接干货。 环境准备 系统&#xff1a;Windows 10/11Python&#xff1a;3.9&#xff08;别用别的版…...

【设计模式】面向对象开发学习OOPC

PLOOC-裸机思维 PLOOC OOPC精要——撩开“对象”的神秘面纱 C/C面向对象编程之封装-KK 面向过程&#xff0c;本质是“顺序&#xff0c;循环&#xff0c;分支”面向对象&#xff0c;本质是“继承&#xff0c;封装&#xff0c;多态”参考的书籍&#xff1a;《UMLOOPC嵌入式C语言…...

LVGL开发指南

一、主流ARM开发UI界面库 主流ARM开发UI界面库的详细对比分析,从多个维度评估各库的适用场景: 1. 基础对比表 特性LVGLQt for MCUEmbedded WizardTouchGFXemWin许可证MIT开源商业商业商业(STM32免费)商业RAM最小需求16KB512KB64KB256KB50KBFlash占用64KB+1MB+200KB+500KB+1…...

linux shell looop循环写法

在 Linux Shell 中编写loop循环的常见方法有以下几种&#xff0c;适用于持续执行任务或监控场景&#xff1a; 1. while true 循环&#xff08;最常用&#xff09; while true; do# 循环体内的命令echo "Running..."sleep 1 # 避免 CPU 占用过高 done 终止方式&…...

【力扣hot100题】(075)数据流的中位数

一开始只建立了一个优先队列&#xff0c;每次查询中位数时都要遍历一遍于是喜提时间超限&#xff0c;看了答案才恍然大悟原来还有这么聪明的办法。 方法是建立两个优先队列&#xff0c;一个大根堆一个小根堆&#xff0c;大根堆记录较小的数&#xff0c;小根堆记录较大的数。 …...

蓝桥杯刷题总结 + 应赛技巧

当各位小伙伴们看到这篇文章的时候想必蓝桥杯也快开赛了&#xff0c;那么本篇文章博主就来总结一下一些蓝桥杯的应赛技巧&#xff0c;那么依旧先来走个流程 那么接下来我们分成几个板块进行总结 首先是一些基本语法 编程语言的基本语法 首先是数组&#xff0c;在存数据的时候…...

JetBrains Terminal 又发布新架构,Android Studio 将再次迎来新终端

不到一年的时间&#xff0c;JetBrains 又要对 Terminal 「大刀阔斧」&#xff0c;本次发布的新终端是重构后的全新的架构&#xff0c;而上一次终端大调整还是去年 8 月的 v2024.2 版本&#xff0c;并且在「Android Studio Ladybug | 2024.2.1」也被引入。 不知道你们用不用内置…...

怎么构造思维链数据?思维链提示工程的五大原则

我来为您翻译这篇关于思维链提示工程的文章&#xff0c;采用通俗易懂的中文表达&#xff1a; 思维链(CoT)提示工程是生成式AI(GenAI)中一种强大的方法&#xff0c;它能让模型通过逐步推理来解决复杂任务。通过构建引导模型思考过程的提示&#xff0c;思维链能提高输出的准确性…...

mongodb--用户管理

文章目录 MongoDB 用户管理1. 连接到 MongoDB2. 用户创建2.1 创建管理员用户2.2 创建特定数据库用户2.3 常用内置角色 3. 用户管理操作3.1 查看所有用户3.2 查看特定用户信息3.3 更新用户密码3.4 添加用户角色3.5 移除用户角色3.6 删除用户 4. 权限修改4.1 创建自定义角色4.2 将…...

2025年考OCP认证有用吗?

在数字化转型的浪潮中&#xff0c;数据库管理技术成为企业核心竞争力的基石。Oracle作为全球领先的数据库解决方案提供商&#xff0c;其OCP&#xff08;Oracle Certified Professional&#xff09;认证不仅是技术能力的权威背书&#xff0c;更是职业发展的强力引擎。以下从多个…...

川翔云电脑:D5 渲染摆脱硬件限制,云端高效创作

在设计领域&#xff0c;D5 渲染器凭借实时光追技术、高效工作流程及优质输出效果&#xff0c;成为设计师的得力工具。然而&#xff0c;其对高端 RTX 显卡的依赖&#xff0c;导致硬件成本高、本地性能受限及办公地点固定等问题&#xff0c;让不少创作者望而却步。 D5 渲染器的优…...

设计模式(23种设计模式简介)

设计模式 简介 设计模式是解决软件设计中常见问题的可重用解决方案模板&#xff0c;通过总结反复验证的代码设计经验&#xff0c;提升代码的可重用性、可维护性和扩展性。其核心是通过标准化的设计思想&#xff0c;让代码更易理解、协作更高效&#xff0c;并在面向对象编程中…...

Python设计模式:工厂模式

1. 什么是工厂模式&#xff1f; 工厂模式是一种创建对象的设计模式&#xff0c;它提供了一种创建对象的接口&#xff0c;但不暴露对象创建的具体逻辑。工厂模式的核心思想是将对象的创建与使用分离&#xff0c;从而提高代码的灵活性和可维护性。 1.1 工厂模式的类型 1.1.1 简…...

UE5 给函数分类

如果函数太多不方便找&#xff0c;我们可以给函数设置一个分组 选中一个函数&#xff0c;修改它的类别 然后在函数列表里可以看到分好的类 其他函数可以直接拖进类别里&#xff0c;不用每个函数都手动设置类别 一次只能拖动一个函数...

5️⃣ Coze+AI应用基础教学(2025年全新版本)

目录 一、了解应用开发 1.1 扣子应用能做什么 1.2 开发流程 1.3 开发环境 二、快速搭建一个AI应用 2.1 AI翻译应用介绍 2.2 设计你的应用功能 2.3 创建 AI 应用项目 2.4 编写业务逻辑&#xff08;新建工作流&#xff09; 2.5 搭建用户界面 2.6 效果测试 2.7 发布应…...

高级前端题库

前端题库 JS篇 如何理解作用域和作用域链 作用域 作用域就是变量或函数在其内能够被访问的“可见区域” 全局作用域局部作用域 作用域链 当在某个作用域中尝试访问一个变量时&#xff0c;JS引擎会从当前作用域开始&#xff0c;沿着作用域链向上逐级开始查找&#xff0c;直到…...

博途 TIA Portal之1200做主站与汇川EASY的TCP通讯

前言,虽然已经做了几篇关于TCP通讯的文章,但是不同的PLC之间的配合可能不同,下面将演示这种差异。 关于汇川EASY做从站的配置请参见下方链接文章:汇川EASY系列之以太网通讯(套接字socket做从站)_汇川以太网tcp套接字fb块-CSDN博客 1、硬件准备: 1200PLC,汇川EASY320…...

在conda虚拟环境安装GIT并且克隆github上项目指南(解决443问题)

此次笔记记录自己在conda虚拟环境安装git&#xff0c;同时克隆github项目&#xff0c;并且解决了git的443问题。 如有不妥欢迎各位大佬批评指正。 首先默认你已经安装了anaconda。 代开命令提示行 配置环境 #首先创建虚拟环境 conda create -n git_env python3.8 #激活虚拟环…...

JavaWeb遇到的问题汇总

问题一&#xff1a;&#xff08;键值对最后一项没有逗号&#xff09; 在JSON字符串转自定义对象和自定义对象转JSON字符串时&#xff1a; 如图所示&#xff1a;若忘记删除键值对的最后一项没有逗号时&#xff0c;则下一句转换不会生效&#xff0c;应该删除最后一项的逗号。 解…...

Stable Diffusion + Contronet,调参实现LPIPS最优(带生成效果+指标对比)——项目学习记录

目录 前言 一、数据集&#xff1a;图像文本&#xff0c;部分选取于DeepFashion 二、优化一&#xff0c;img2img 三、优化二&#xff0c;微调sd参数 四、优化三&#xff0c;dreamshaper优化 五、优化四&#xff0c;sdv1.5contronet 六、问题探索历程 1. 从 SDXL 到轻量化模…...