实验二 多线程编程实验
一、实验目的
1、掌握线程的概念,明确线程和进程的区别。
2、学习Linux下线程创建方法及编程。
3、了解线程的应用特点。
4、掌握用锁机制访问临界区实现互斥的方法。
5、掌握用信号量访问临界区实现互斥的方法。
6、掌握线程下用信号量实现同步操作的方法。
二、实验内容
1、运行下列程序,给出执行结果,并分析运行结果。(3分)
1) #include <stdio.h>
#include <pthread.h>
#include <unistd.h>
// 打印函数(在屏幕上显示字符串)
void printer(char *str){
while(*str!='\0')
{ putchar(*str);
fflush(stdout);
str++;
sleep(1);
}
printf("\n");
}
// 线程一
void *thread_fun_1(void *arg)
{
char *str = "hello";
printer(str); //调用打印函数
}
// 线程二
void *thread_fun_2(void *arg)
{
char *str = "world";
printer(str); //调用打印函数
}
int main(void)
{
pthread_t tid1, tid2;
// 创建 2 个线程
pthread_create(&tid1, NULL, thread_fun_1, NULL);
pthread_create(&tid2, NULL, thread_fun_2, NULL);
// 等待线程结束,回收其资源
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
return 0;
}
编译及执行过程和运行结果截屏:
结果分析:
线程一和线程二,它们分别打印"hello"和"world"字符串。主线程使用pthread_join函数等待两个线程结束。
由于并发执行的原因,线程一和线程二的打印操作会交替进行,输出的结果可能是"howorldello"、"howerlllod"等不确定的顺序。
每个字符之间有1秒的延迟,所以输出的结果中每个字符之间会有间隔。最后输出一个换行符,每次执行的结果都会在新的一行显示。
- #include <stdio.h>
#include <pthread.h>
#include <unistd.h>
pthread_mutex_t mutex_x=PTHREAD_MUTEX_INITIALIZER;//定义并初始化锁
//打印函数(在屏幕上显示字符串)
void printer(char *str)
{
pthread_mutex_lock(&mutex_x);//上锁
while(*str!='\0')
{
putchar(*str);
fflush(stdout);
str++;
sleep(1);
}
printf("\n");
pthread_mutex_unlock(&mutex_x);//解锁
}
// 线程一
void *thread_fun_1(void *arg)
{
char *str = "hello";
printer(str); //调用打印函数
}
// 线程二
void *thread_fun_2(void *arg)
{
char *str = "world";
printer(str); //调用打印函数
}
int main(void)
{
pthread_t tid1, tid2;
// 创建 2 个线程
pthread_create(&tid1, NULL, thread_fun_1, NULL);
pthread_create(&tid2, NULL, thread_fun_2, NULL);
// 等待线程结束,回收其资源
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
pthread_mutex_destroy(&mutex_x); //销毁互斥锁
return 0;
}
编译及执行过程和运行结果截屏:
结果分析:
在程序中创建了两个线程,分别执行thread_fun_1和thread_fun_2函数。这两个函数都调用了printer函数,每次调用时都会上锁mutex_x,然后通过putchar函数逐个打印字符串中的字符,并休眠1秒钟。
由于两个线程同时运行,打印函数的执行是交替进行的。线程一先执行,打印"hello",然后释放锁,线程二获取到锁,打印"world",最后两个线程结束。
所以最终的输出结果为"hello world"。
- #include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <semaphore.h>
sem_t semA; //声明一个名为semA的信号量变量
//打印函数(在屏幕上显示字符串)
void printer(char *str)
{
sem_wait(&semA);//申请信号量(P操作)
while(*str!='\0')
{
putchar(*str);
fflush(stdout);
str++;
sleep(1);
}
printf("\n");
sem_post(&semA);//释放信号量(V操作)
}
// 线程一
void *thread_fun_1(void *arg)
{
char *str = "hello";
printer(str); //调用打印函数}
// 线程二
void *thread_fun_2(void *arg)
{
char *str = "world";
printer(str); //调用打印函数}
int main(void)
{
pthread_t tid1, tid2;
if(sem_init(&semA, 0, 1)) //初始化信号量的值为1(二元信号量)
printf("error sem_init!\n");
// 创建 2 个线程
pthread_create(&tid1, NULL, thread_fun_1, NULL);
pthread_create(&tid2, NULL, thread_fun_2, NULL);
// 等待线程结束,回收其资源
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
sem_destroy(&semA); //销毁信号量
return 0;
}
编译及执行过程和运行结果截屏:
结果分析:
在主函数中,创建了两个线程,分别调用了thread_fun_1和thread_fun_2函数。这两个函数内部调用了printer函数。由于两个线程同时调用printer函数,但是通过信号量的控制,确保了只有一个线程可以打印字符,另一个线程在sem_wait(&semA)处等待。因此,打印的结果是"helloworld"。
2、通过多线程模拟多窗口售票,在主线程下创建4个子线程,模拟4个售票窗口,假设有20张票待售,运行该程序看会有什么样的结果,分析程序和执行结果。(1分)
<参考程序>
#include<pthread.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<semaphore.h>
#include<stdint.h>
int ticket_sum=20;
void *sell_ticket(void *arg)
{
int i;
for(i=0;i<20;i++)
{
if(ticket_sum>0)
{
sleep(1);
printf("sell the %dth\n",20-ticket_sum+1);
ticket_sum--;
}
}
return 0;
}
int main()
{
int flag,i;
pthread_t tids[4];
for(i=0;i<4;i++)
{
flag=pthread_create(&tids[i],NULL,&sell_ticket,NULL);//创建线程
if(flag)
{
printf("pthread create error ,flag=%d",flag);
return flag;
}
}
sleep(20);
void *ans;
for(i=0;i<4;i++)
{
flag=pthread_join(tids[i],&ans);//等待线程结束
if(flag)
{
printf("tid=%lu,join erro flag=%d",tids[i],flag);
return flag;
}
printf("ans=%ld\n",(intptr_t)ans);
}
return 0;
}给出编译及执行过程和运行结果:(部分截屏)
结果分析:
该程序创建了4个线程,每个线程都执行sell_ticket函数。在sell_ticket函数中,使用一个循环进行售票操作,每次售票后ticket_sum减1,直到ticket_sum为0结束循环。
在主函数中,创建4个线程,并等待线程完成。等待线程完成后,打印线程的返回值,此处返回值为0。
3、修改上题,用锁机制实现线程互斥进入临界区,解决售票窗口超卖问题。要求给出编译及运行过程和结果截图。 (2分)
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include<semaphore.h>
#include<stdint.h>
int ticket_sum = 20; // 总票数
pthread_mutex_t mutex; // 定义互斥锁
void *sell_ticket(void *arg)
{
int ticket_count = 0; // 售出的票数
while (1) {
pthread_mutex_lock(&mutex); // 上锁
if (ticket_sum > 0) {
sleep(1); // 模拟售票耗时
printf("sell the %d th\n", 20 - ticket_sum + 1);
ticket_sum--;
ticket_count++;
} else {
pthread_mutex_unlock(&mutex); // 解锁
break;
}
pthread_mutex_unlock(&mutex); // 解锁
}
pthread_exit((void *)ticket_count); // 返回售出的票数
}
int main()
{
pthread_t tids[4]; // 线程数组
int i;
int ticket_count = 0; // 总共售出的票数
pthread_mutex_init(&mutex, NULL); // 初始化互斥锁
for (i = 0; i < 4; i++) {
pthread_create(&tids[i], NULL, sell_ticket, NULL); // 创建线程
}
for (i = 0; i < 4; i++) {
void *ret;
pthread_join(tids[i], &ret); // 等待线程结束
ticket_count += (intptr_t)ret; // 统计每个线程售出的票数
}
printf("总共售出了 %d 张票\n", ticket_count);
pthread_mutex_destroy(&mutex); // 销毁互斥锁
return 0;
}
给出编译及执行过程和运行结果:(部分截屏)
4、修改实验内容2,用信号量实现线程互斥进入临界区,解决售票窗口超卖问题。要求给出编译及执行过程和结果截屏。(2分)
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include<semaphore.h>
#include<stdint.h>
#define TOTAL_TICKETS 20
int tickets = TOTAL_TICKETS;
sem_t semaphore;
void *sellTicket(void *arg) {
char *sellerName = (char *)arg;
while (1) {
sem_wait(&semaphore); // 获得信号量,进入临界区
if (tickets > 0) {
tickets--;
printf("sell the %dth\n", 20-tickets);
} else {
printf("没有票了\n");
sem_post(&semaphore); // 离开临界区
break;
}
sem_post(&semaphore); // 离开临界区
usleep(100000); // 模拟售票过程的耗时操作
}
return NULL;
}
int main() {
pthread_t sellers[4];
sem_init(&semaphore, 0, 1);
char *sellerNames[4] = {"售票窗口1", "售票窗口2", "售票窗口3", "售票窗口4"};
for (int i=0; i<4; i++) {
pthread_create(&sellers[i], NULL, sellTicket, (void *)sellerNames[i]);
}
for (int i=0; i<4; i++) {
pthread_join(sellers[i], NULL);
}
sem_destroy(&semaphore);
return 0;
}
给出编译及执行过程和运行结果:(部分截屏)
5、利用线程和信号量机制实现司机售票员同步操作问题。(1分)
参考程序框架:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <semaphore.h>
sem_t door, stop; // 设置关门和停车两个信号量
void *thread_driver(void *arg) // 司机线程
{
while (1)
{
sem_wait(&door); // P(door),等待售票员的关门信号
printf("司机: 启动汽车\n");
printf("司机: 驾驶汽车\n");
sleep(1);
printf("司机: 到站停车\n");
sem_post(&stop); // V(stop),发送停车信号
}
}
void *thread_conductor(void *arg) // 售票员线程
{
while (1)
{
printf("售票员: 关门\n");
sem_post(&door); // V(door),发送关门信号
printf("售票员: 卖票\n");
sem_wait(&stop); // P(stop),等待司机的停车信号
printf("售票员: 开门\n");
printf("乘客上下车\n");
sleep(1);
}
}
int main()
{
int sg1, sg2;
pthread_t driver, conductor; // 定义两个变量存放线程标识符
sg1 = sem_init(&door, 0, 0); // 初始化关门信号量door,初始值为0
sg2 = sem_init(&stop, 0, 0); // 初始化停车信号量stop,初始值为0
pthread_create(&driver, NULL, (void *)thread_driver, NULL); // 创建司机线程
pthread_create(&conductor, NULL, (void *)thread_conductor, NULL); // 创建售票员线程
pthread_join(driver, NULL); // 等待司机线程结束
pthread_join(conductor, NULL); // 等待售票员线程结束
sem_destroy(&door); // 销毁关门信号量
sem_destroy(&stop); // 销毁停车信号量
return 0;
}
编译及执行过程和结果截屏:
6、利用线程和信号量实现生产者消费者问题(涉及线程同步和互斥问题)。(附加题)
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <semaphore.h>
#define BUFFER_SIZE 5
int buffer[BUFFER_SIZE];
sem_t mutex, empty, full;
int in = 0;
int out = 0;
void *producer(void *arg) {
int item;
while (1) {
item = rand() % 100; // 生产一个随机数作为产品
sem_wait(&empty); // 等待空缓冲区
sem_wait(&mutex); // 互斥访问缓冲区
printf("Produced item: %d\n", item);
buffer[in] = item;
in = (in + 1) % BUFFER_SIZE;
sem_post(&mutex); // 释放互斥锁
sem_post(&full); // 增加满缓冲区的信号量
sleep(1); // 生产速度较慢,方便观察
}
}
void *consumer(void *arg) {
int item;
while (1) {
sem_wait(&full); // 等待满缓冲区
sem_wait(&mutex); // 互斥访问缓冲区
item = buffer[out];
out = (out + 1) % BUFFER_SIZE;
printf("Consumed item: %d\n", item);
sem_post(&mutex); // 释放互斥锁
sem_post(&empty); // 增加空缓冲区的信号量
sleep(1); // 消费速度较慢,方便观察
}
}
int main() {
pthread_t producer_thread, consumer_thread;
sem_init(&mutex, 0, 1); // 初始化互斥锁
sem_init(&empty, 0, BUFFER_SIZE); // 初始化空缓冲区的信号量
sem_init(&full, 0, 0); // 初始化满缓冲区的信号量
pthread_create(&producer_thread, NULL, producer, NULL);
pthread_create(&consumer_thread, NULL, consumer, NULL);
pthread_join(producer_thread, NULL);
pthread_join(consumer_thread, NULL);
sem_destroy(&mutex); // 销毁互斥锁
sem_destroy(&empty); // 销毁空缓冲区的信号量
sem_destroy(&full); // 销毁满缓冲区的信号量
return 0;
}
编译及执行过程和结果截屏:
三、实验总结和体会
通过这次实验,我对操作系统中多线程编程有了更深入的了解和实践经验。在实验中,我学习了使用多线程编程来实现并发任务的处理,以及线程间的同步和互斥机制。
首先,我学会了使用线程创建函数来创建和启动新线程。我了解到线程是程序中的并发执行流,可以并行处理任务,提高程序的执行效率。在实验中,我通过使用pthread库中的函数,如pthread_create()来创建线程,并指定线程函数进行任务处理。
其次,我学会了使用互斥锁来保护共享资源的访问。在多线程编程中,当多个线程需要同时访问共享资源时,可能会导致竞态条件和数据不一致的问题。为了避免这些问题,我使用了互斥锁来实现线程间的互斥访问。通过使用pthread库中的函数,如pthread_mutex_init()和pthread_mutex_lock()等,我可以对关键代码段进行上锁,使得同一时间只有一个线程可以访问共享资源。
此外,我还学习了使用条件变量来实现线程间的通信和同步。条件变量可以用于线程间的等待和唤醒操作,使得线程可以在特定条件满足时才进行执行。通过使用pthread库中的函数,如pthread_cond_init()和pthread_cond_wait()等,我可以实现线程的等待和唤醒操作,以实现线程间的同步和协作。
通过这次实验,我对操作系统中多线程编程的原理和实践有了更深入的理解。我认识到多线程编程可以提高程序的并发性和效率,但也需要考虑线程间的同步和互斥,以及资源管理和性能优化等方面。我意识到多线程编程的复杂性和挑战,但也体会到了并发编程的用处
相关文章:
实验二 多线程编程实验
一、实验目的 1、掌握线程的概念,明确线程和进程的区别。 2、学习Linux下线程创建方法及编程。 3、了解线程的应用特点。 4、掌握用锁机制访问临界区实现互斥的方法。 5、掌握用信号量访问临界区实现互斥的方法。 6、掌握线程下用信号量实现同步操作的方法。 …...
密码学(1)LWE,RLWE,MLWE的区别和联系
一、定义与基本概念 LWE(Learning With Errors): 定义:LWE问题是在给定一个矩阵A和一个向量b^Axe(其中e是一个固定数值范围内随机采集的随机噪音向量)的情况下,求解未知的向量x。本质࿱…...
数据结构-链表
目录 一、链表的基本概念单链表定义双链表定义 二、链表的基本操作1. 创建链表2. 遍历链表3. 插入节点4. 删除节点5. 反转链表 三、链表的实际应用1. 操作系统中的内存管理2. 文件系统中的目录结构3. 浏览器历史记录 四、链表的优缺点优点缺点 五、总结 一、链表的基本概念 链…...
go中redis使用的简单介绍
目录 一、Redis 简介 二、Go中Redis的使用 1. 安装Go Redis包 2. 单机模式 连接示例 3. 哨兵模式 依赖 连接示例 三、Redis集群 1. 集群模式 集群部署 部署结构 使用redis-cli创建集群 连接示例 四、常用数据结构与操作 1. 字符串(String࿰…...
使用 JUnit 4在 Spring 中进行单元测试的完整步骤
以下是使用 JUnit 4 在 Spring 中进行单元测试的完整步骤,包含配置、核心注解、测试场景及代码示例: 1. 添加依赖 在 pom.xml 中引入必要的测试依赖(以 Spring 4/5 JUnit 4 为例): <!-- JUnit 4 --> <depe…...
第七节:进阶特性高频题-Vue3的ref与reactive选择策略
ref:基本类型(自动装箱为{ value: … }对象) reactive:对象/数组(直接解构会丢失响应性,需用toRefs) 一、核心差异对比 维度refreactive适用类型基本类型(string/number/boolean&a…...
Redis 详解:安装、数据类型、事务、配置、持久化、订阅/发布、主从复制、哨兵机制、缓存
目录 Redis 安装与数据类型 安装指南 Windows Linux 性能测试 基本知识 数据类型 String List(双向列表) Set(集合) Hash(哈希) Zset(有序集合) 高级功能 地理位置&am…...
第十篇:系统分析师第三遍——7、8章
目录 一、目标二、计划三、完成情况四、意外之喜(最少2点)1.计划内的明确认知和思想的提升标志2.计划外的具体事情提升内容和标志 五、总结 一、目标 通过参加考试,训练学习能力,而非单纯以拿证为目的。 1.在复习过程中,训练快速阅读能力、掌…...
从 Vue 到 React:React.memo + useCallback 组合技
目录 一、Vue 与 React 的组件更新机制对比二、React.memo 是什么?三、常见坑:为什么我用了 React.memo 还是会重新渲染?四、解决方案:useMemo / useCallback 缓存引用五、Vue 3 中有类似的性能控制需求吗?六、组合优化…...
1656打印路径-Floyd/图论-链表/数据结构
蓝桥账户中心 1.税收: “城市的税收”:所以是中介点的税收,经过该点后加上 2.路径: 用数组存储前驱节点从而串成链表 pre[ i ][ j ]代表的是从 i 到 j 的最短路径上 j 的前驱节点是什么 那么便可以pre[ i ][ j ]k 把k加入pa…...
Linux网络编程 从集线器到交换机的网络通信全流程——基于Packet Tracer的深度实验
这里我们先下载一个软件:Packet Tracer 用来搭建网络拓扑图的,是模拟和查看数据在网络中传输的详细过程的 在软件这里可以添加设备 知识点1【集线器】(Hub) 1、先配置一下主机的IP 这里我们设置IP一定要在同一个网段ÿ…...
深入学习Axios:现代前端HTTP请求利器
文章目录 深入学习Axios:现代前端HTTP请求利器一、Axios简介与安装什么是Axios?安装Axios 二、Axios基础使用发起GET请求发起POST请求并发请求 三、Axios高级特性创建Axios实例配置默认值拦截器取消请求 四、Axios与TypeScript五、最佳实践1. 封装Axios2…...
FANUC机器人GI与GO位置数据传输设置
FANUC机器人GI与GO位置数据传输设置(整数小数分开发) 一、概述 在 Fanuc 机器人应用中,如果 IO 点位足够,可以利用机器人 IO 传输位置数据及偏移位置数据等。 二、操作步骤 1、确认通讯软件安装 首先确认机器人控制柜已经安装…...
微服务 RabbitMQ 组件的介绍、安装与使用详解
微服务 RabbitMQ 组件的介绍、安装与使用 在现代微服务架构中,服务之间的通信通常采用消息队列的方式,来解耦服务之间的依赖、提高系统的可靠性和扩展性。RabbitMQ 作为一种高效、可靠的消息队列系统,已经广泛应用于微服务架构中。本文将介绍…...
Vue3速通笔记
Vue3入门到实战 尚硅谷Vue3入门到实战,最新版vue3TypeScript前端开发教程 1. Vue3简介 2020年9月18日,Vue.js发布版3.0版本,代号:One Piece(n经历了:4800次提交、40个RFC、600次PR、300贡献者官方发版地…...
Spring Boot 项目:如何在 JAR 运行时读取外部配置文件
在 Spring Boot 项目中,我们常常需要在生产环境中灵活地配置应用,尤其是当我们将项目打包为 JAR 文件时,如何在运行时通过外部配置文件(如 application.yml 或 application.properties)替换 JAR 内部的配置就变得尤为重…...
Certimate本地化自动化 SSL/TLS 证书管理解决方案
一、背景与挑战 多域名管理复杂 运维团队往往需要为多个子域、泛域名乃至不同项目的域名分别申请证书,手动操作容易出错且耗时。续期易忘风险 主流免费证书(如 Let’s Encrypt)有效期仅 90 天,需要定期续期,人工监控门…...
vue+flask+lstm高校舆情分析系统 | 可获取最新数据!
文章结尾部分有CSDN官方提供的学长 联系方式名片 文章结尾部分有CSDN官方提供的学长 联系方式名片 关注B站,有好处! 编号:F020 gaoxiao 架构:vueflaskLSTMMySQL 功能: 微博信息爬取、情感分析、基于负面消极内容舆情分…...
Cisco-Torch:思科设备扫描器!全参数详细教程!Kali Linux教程!
简介 cisco-torch 与同类工具的主要区别在于其广泛使用 fork 技术,可以在后台启动多个扫描进程,从而最大限度地提高扫描效率。此外,它还可以根据需要同时使用多种应用层指纹识别方法。我们希望能够快速发现运行 Telnet、SSH、Web、NTP、TFTP…...
Go协程的调用与原理
Goroutine Go不需要像C或者Java那样手动管理线程,Go语言的goroutine机制自动帮你管理线程。 使用goroutine、 Go语言中使用goroutine非常简单,只需要在调用函数的时候在前面加上go关键字,就可以为一个函数创建一个goroutine。 一个gorout…...
论文精读:大规模MIMO波束选择问题的量子计算解决方案
论文精读:大规模MIMO波束选择问题的量子计算解决方案 概要: 随着大规模多输入多输出系统(MIMO)在5G及未来通信技术中的应用,波束选择问题(MBS)成为提升系统性能的关键。传统的波束选择方法面临计…...
将 MySQL 8 主从复制延迟优化到极致
目录 一、网络资源不足引起的复制延迟 1. 执行监控确认延迟原因 2. 估算所需带宽 (1)基本公式 (2)实际测量方法 二、大事务或大查询引起的复制延迟 1. 主库大事务 2. 从库大查询 3. 估算所需 I/O 能力 (1&am…...
路由与OSPF学习
【路由是跨网段通讯的必要条件】 路由指的是在网络中,数据包从源主机传输到目的主机的路径选择过程。 路由通常涉及以下几个关键元素: 1.路由器:是一种网络设备,负责将数据包从一个网络传输到另一个网络。路由器根据路由表来决定…...
Spring Security:企业级安全架构的设计哲学与工程实践
一、核心架构与设计理念 Spring Security作为Spring生态中的安全基石,其架构设计遵循**“分层过滤"与"组件化扩展”**两大原则。整个安全框架本质上是一个由多个过滤器构成的链式处理模型(Filter Chain),每个过滤器负责…...
NLP高频面试题(五十二)——BERT 变体详解
在现代自然语言处理领域,BERT 系列模型不断演进,衍生出多种变体,它们通过改进预训练任务、模型结构和训练策略,在不同应用场景下取得了更优表现。本文首先概览主要 BERT 变体(如 ALBERT、RoBERTa、ELECTRA、SpanBERT、Transformer-XL 等),随后针对以下几个关键问题逐一展…...
C++Primer 编程练习 第二章
最近想重新看一下CPrimer,顺便敲一下他的编程练习题,虽然很简单,但是就当是锻炼一下vim的熟练度和手感 由于按照章节顺序来说是初学者,不会对输入内容做过多的判断,只对问题作出基本实现 第二章 1 #include <ios…...
Vue.js 新手小白指南:从起源到实战
🌟 Vue 的来源 Vue.js 由**尤雨溪(Evan You)**在2014年创建,最初是作为个人项目开发,灵感来源于他在 Google 使用 AngularJS 的经验。Vue 的设计目标是提供一个更轻量级、更易上手的前端框架。 如今,Vue …...
策略模式:动态切换算法的设计智慧
策略模式:动态切换算法的设计智慧 一、模式核心:定义一系列算法并可相互替换 在软件开发中,常常会遇到需要根据不同情况选择不同算法的场景。例如,在电商系统中,根据不同的促销活动(如满减、折扣、赠品&a…...
Vm免安装直接使用虚拟机win7系统
教程 一、下载并解压资料里面的vmx压缩包 二、使用Vm软件打开刚刚解压的vmx文件即可使用虚拟机的win7系统 资料下载 点击下载...
LSTM-GAN生成数据技术
1. 项目概述 本项目利用生成对抗网络(GAN)技术来填补时间序列数据中的缺失值。项目实现了两种不同的GAN模型:基于LSTM的GAN(LSTM-GAN)和基于多层感知机的GAN(MLP-GAN),并对两种模型…...
26、C# 中是否可以继承String类?为什么?
在 C# 中,不能直接继承 String 类(System.String)。这是由于以下几个原因: 1、String 类是 sealed 的 String 类在 .NET 中被标记为 sealed,这意味着它是一个密封类,不能被继承。 sealed 关键字的作用是防…...
gem5教程第五章 了解gem5默认配置脚本
在本章中,我们将探讨如何使用gem5附带的默认配置脚本。 gem5附带了许多配置脚本,使您能够非常快速地使用gem5。 然而,一个常见的陷阱是在不完全理解所模拟内容的情况下使用这些脚本。在使用gem5进行计算机架构研究时,充分了解您正在模拟的系统非常重要。本章将引导您了解默…...
什么是鸿蒙南向开发?什么是北向开发?
文章目录 鸿蒙南向开发 vs 北向开发:底层与生态的双向赋能一、鸿蒙南向开发:连接硬件的底层基石二、鸿蒙北向开发:构建全场景应用生态三、南向与北向:互补与协同四、如何选择开发方向?结语 鸿蒙南向开发 vs 北向开发:…...
蓝桥杯 19. 最大比例
最大比例 原题目链接 题目描述 X 星球的某个大奖赛设了 M 级奖励。每个级别的奖金是一个正整数。 并且,相邻两个级别间的比例是一个固定值,也就是说:所有级别的奖金构成一个等比数列。 例如: 奖金数列为 16, 24, 36, 54&…...
制造业数字化转型标杆解析:从冀凯机电到君乐宝的启示
1. 执行摘要 数字化转型已成为现代制造业提升竞争力、实现高质量发展的核心驱动力。本文旨在通过深入剖析冀凯装备制造股份有限公司(冀凯机电)和君乐宝乳业集团(君乐宝)两家不同行业背景企业的数字化转型实践,提炼可供…...
【OSCP-vulnhub】Raven-2
目录 端口扫描 本地/etc/hosts文件解析 目录扫描: 第一个flag 利用msf下载exp flag2 flag3 Mysql登录 查看mysql的运行权限 MySql提权:UDF 查看数据库写入条件 查看插件目录 查看是否可以远程登录 gcc编译.o文件 创建so文件 创建临时监听…...
配置MambaIRv2: Attentive State Space Restoration的环境
github上代码的地址: csguoh/MambaIR: [ECCV2024, CVPR2025] MambaIR and MambaIRv2! 一开始直接输入命令 conda env create -f environment.yaml 安装了半天爆出来好几个错误,其中一个是没有nvcc 输入以下命令: module avail 发现没有…...
4.23晚间工作总结
主要工作:将ClassicDetail界面拆分成utils,apis,stores,css,vue多个文件,方便后续重用 具体代码截图:...
Maven 项目中引入本地 JAR 包
在日常开发过程中,我们有时会遇到一些未上传到 Maven 中央仓库或公司私有仓库的 JAR 包,比如第三方提供的 SDK 或自己编译的库。这时候,我们就需要将这些 JAR 包手动引入到 Maven 项目中。本文将介绍两种常见方式:将 JAR 安装到本…...
SpringBoot整合SSE,基于okhttp
一、引入依赖 <dependency><groupId>com.squareup.okhttp3</groupId><artifactId>okhttp</artifactId><version>4.10.0</version> </dependency> <dependency><groupId>com.squareup.okhttp3</groupId><…...
从云端到边缘:云原生后端架构在边缘计算中的演进与实践
📝个人主页🌹:慌ZHANG-CSDN博客 🌹🌹期待您的关注 🌹🌹 一、引言:为何云原生后端正在走向边缘? 随着物联网(IoT)、5G 和实时应用的快速发展,越来越多的数据在终端产生并需要即时处理。传统云计算虽强大,但将所有数据上送云端再处理,带来高延迟与带宽压力。…...
pytest心得体会
一、如何单独运行某条用例 在参数化测试中总有些用例失败,由于前后置数据的关系需要单独运行那条用例如何运行呢 方法一:直接查看控制台运行用例 确定是[2-case_data8] pytest.main(["-sv","testcase/违规告警/test_违规告警_非合同车…...
《Cesium 中两点绘制线的实现:实线、虚线、动态线、流动线详解》
摘要 在 Cesium 三维地球可视化开发中,两点之间绘制线是常见的需求。本文详细介绍如何在 Cesium 中实现两点间绘制实线、虚线、动态线和流动线,并提供完整的代码示例,方便开发者快速上手,满足不同场景下的可视化需求。 一、环境与依赖 本文代码基于 Cesium 库进行开发,…...
【EasyPan】MySQL FIELD() 函数实现自定义排序
【EasyPan】项目常见问题解答(自用&持续更新中…)汇总版 MySQL FIELD() 函数解析 一、FIELD() 函数技术解析 /* 基础语法 */ FIELD(column_name, value1, value2, ..., valueN)核心特性 特性说明返回值机制返回字段值在参数列表中的索引位置&…...
搭建TypeScript单元测试环境
我们在学习TypeScript的时候如果能够搭建一个单元测试的环境,那写些demo会很简单,下面我们使用jest来搭建一个单元测试环境 Jest 是一个由 Facebook 开发并开源的 JavaScript 测试框架,被广泛应用于前端和 Node.js 项目的单元测试。以下是关…...
Vue3父子组件数据同步方法
在 Vue 3 中,当子组件需要修改父组件传递的数据副本并同步更新时,可以通过以下步骤实现: 方法 1:使用 v-model 和计算属性(实时同步) 父组件: vue <template><ChildComponent v-mo…...
免费且开源的企业级监控解决方案:Zabbix
一、Zabbix 简介 Zabbix 是一款功能强大的企业级开源监控解决方案。它可以监控各种 IT 基础设施组件,包括网络设备、服务器、虚拟机、云服务、应用程序和数据库等。Zabbix 提供实时的监控、告警、报表和可视化功能,帮助用户及时发现和解决 IT 系统中的问…...
高并发系统的通用设计方法是什么?
背景 高并发系统的通用设计方法是解决系统在面对大量用户访问时的性能瓶颈问题。当系统遇到性能瓶颈时,通常是因为某个单点资源(如数据库、后端云服务器、网络带宽等)达到了极限。 为了提升整个系统的容量,需要找到这个瓶颈资源…...
ubuntu系统下部署使用git教程
在ubuntu系统下部署并使用git教程 1.下载并安装 sudo apt update sudo apt install git2.检验安装是否成功 git --version若输出git版本号即为成功。 3.配置参数 git config --global user.name "你的名字" git config --global user.email "你的邮箱&quo…...
redis client.ttl(key)
对应 Redis 的 TTL 命令: bash 复制 下载 TTL key 使用示例 1. 基本用法 java 复制 下载 try (Jedis jedis jedisPool.getResource()) {long ttl jedis.ttl("user:1001:session");if (ttl > 0) {System.out.println("键将在 " t…...