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

【Linux探索学习】第三十一弹——线程互斥与同步(下):深入理解确保线程安全的机制

线程互斥与同步(上):【Linux探索学习】第三十弹——线程互斥与同步(上):深入理解线程保证安全的机制-CSDN博客

Linux探索学习:

https://blog.csdn.net/2301_80220607/category_12805278.html?spm=1001.2014.3001.5482

前言:

在上一篇中我们已经讲解了线程互斥与同步中关于互斥的相关知识点,今天我们来学习一下Linux中线程同步的相关知识点。其实要想做到线程同步,首先就要确保线程互斥部分是没问题的,也就是说做好线程互斥也是确保线程同步与线程安全的重要一步

在多线程编程中,线程同步是一个至关重要的问题。当多个线程共享同一资源时,如果没有合适的同步机制,可能会导致数据竞争、死锁等问题。Linux提供了多种线程同步机制,如互斥锁(前面讲过)、条件变量、读写锁、信号量等。本文将详细讲解Linux中的线程同步问题,并重点介绍POSIX信号量的使用。

目录

1. 线程同步的基本概念

1.1 什么是线程同步?

1.2 为什么需要线程同步?

2. 条件变量

2.1 条件变量的基本概念

2.2 条件变量的相关函数详解

2.2.1 pthread_cond_init

2.2.2 pthread_cond_destroy

2.2.3 pthread_cond_wait

2.2.4 pthread_cond_signal

2.2.5 pthread_cond_broadcast

2.3 条件变量的使用示例

2.4 运行结果

​编辑

2.5 代码解析

3. 读写锁

3.1 读写锁的基本概念

3.2 读写锁的相关函数详解

3.2.1 pthread_rwlock_init

3.2.2 pthread_rwlock_destroy

3.2.3 pthread_rwlock_rdlock

3.2.4 pthread_rwlock_wrlock

3.2.5 pthread_rwlock_unlock

3.3 读写锁的使用示例

3.4 运行结果

​编辑

3.5 代码解析

4. POSIX信号量

4.1 POSIX信号量的基本概念

4.2 POSIX信号量的相关函数详解

4.2.1 sem_init

4.2.2 sem_destroy

4.2.3 sem_wait

4.2.4 sem_post

4.2.5 sem_trywait

4.2.6 sem_getvalue

4.3 POSIX信号量的使用示例

4.4 运行结果

​编辑

4.5 代码解析

5. 总结

5.1 条件变量的适用场景

5.2 读写锁的适用场景

5.3 POSIX信号量的适用场景

5.4 选择同步机制的考虑因素


1. 线程同步的基本概念

1.1 什么是线程同步?

线程同步是指多个线程在访问共享资源时,通过某种机制来协调它们的执行顺序,以避免数据竞争和不一致性问题。常见的线程同步机制包括互斥锁、条件变量、读写锁、信号量等。

1.2 为什么需要线程同步?

在多线程环境中,多个线程可能会同时访问共享资源。如果没有适当的同步机制,可能会导致以下问题:

  • 数据竞争:多个线程同时修改同一数据,导致数据不一致。

  • 死锁:多个线程相互等待对方释放资源,导致程序无法继续执行。

  • 活锁:线程不断尝试获取资源但总是失败,导致程序无法继续执行。(活锁的具体讲解想了解的可以再搜一下)

2. 条件变量

2.1 条件变量的基本概念

条件变量是一种线程同步机制,用于在多个线程之间传递信号。条件变量通常与互斥锁一起使用,用于在某个条件成立时唤醒等待的线程。

2.2 条件变量的相关函数详解

2.2.1 pthread_cond_init

函数原型:

int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr);

功能:
初始化条件变量。

参数:

  • cond:指向条件变量的指针。

  • attr:条件变量的属性,通常设置为NULL,表示使用默认属性。

返回值:

  • 成功返回0,失败返回错误码。

示例:

pthread_cond_t cond;
pthread_cond_init(&cond, NULL);
2.2.2 pthread_cond_destroy

函数原型:

int pthread_cond_destroy(pthread_cond_t *cond);

功能:
销毁条件变量。

参数:

  • cond:指向条件变量的指针。

返回值:

  • 成功返回0,失败返回错误码。

示例:

pthread_cond_destroy(&cond);
2.2.3 pthread_cond_wait

函数原型:

int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);

功能:
等待条件变量,并释放互斥锁。具体点来说就是需要等待满足条件才能执行下一步,但是在这一步之前我们可能已经获取了锁,为了避免死锁问题,就需要在等待条件变量时把互斥锁释放掉

参数:

  • cond:指向条件变量的指针。

  • mutex:指向互斥锁的指针。

返回值:

  • 成功返回0,失败返回错误码。

示例:

pthread_mutex_lock(&mutex);
while (!ready) {pthread_cond_wait(&cond, &mutex);
}
pthread_mutex_unlock(&mutex);
2.2.4 pthread_cond_signal

函数原型:

int pthread_cond_signal(pthread_cond_t *cond);

功能:
唤醒一个等待条件变量的线程。

参数:

  • cond:指向条件变量的指针。

返回值:

  • 成功返回0,失败返回错误码。

示例:

pthread_cond_signal(&cond);
2.2.5 pthread_cond_broadcast

函数原型:

int pthread_cond_broadcast(pthread_cond_t *cond);

功能:
唤醒所有等待条件变量的线程。在使用这种方式时需要注意,因为有些时候当出现多进程的线程时,这种方法可能会导致线程误唤醒,在我们后面讲生产消费模型的时候会讲到这一点

参数:

  • cond:指向条件变量的指针。

返回值:

  • 成功返回0,失败返回错误码。

示例:

pthread_cond_broadcast(&cond);

2.3 条件变量的使用示例

下面是一个简单的示例,演示了如何使用条件变量来同步两个线程的执行。

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>pthread_mutex_t mutex;
pthread_cond_t cond;
int ready = 0;void* thread_func(void* arg) {pthread_mutex_lock(&mutex);while (!ready) {printf("Thread waiting...\n");pthread_cond_wait(&cond, &mutex);}printf("Thread awakened!\n");pthread_mutex_unlock(&mutex);return NULL;
}int main() {pthread_t tid;pthread_mutex_init(&mutex, NULL);pthread_cond_init(&cond, NULL);pthread_create(&tid, NULL, thread_func, NULL);sleep(1);  // 模拟一些工作pthread_mutex_lock(&mutex);ready = 1;pthread_cond_signal(&cond);pthread_mutex_unlock(&mutex);pthread_join(tid, NULL);pthread_mutex_destroy(&mutex);pthread_cond_destroy(&cond);return 0;
}

2.4 运行结果

Thread waiting...
Thread awakened!

2.5 代码解析

  • pthread_cond_wait(&cond, &mutex):线程在等待条件变量时,会释放互斥锁,并在被唤醒后重新获取互斥锁。

  • pthread_cond_signal(&cond):唤醒一个等待条件变量的线程。

  • pthread_cond_broadcast(&cond):唤醒所有等待条件变量的线程。

这里的这个代码比较简单,也没有什么现实意义,重要的是先要理解一下条件变量的出现场景和使用,条件变量一般是和互斥锁同时出现的,能够确保在满足条件的情况下才能执行临界区的语句

3. 读写锁

3.1 读写锁的基本概念

读写锁是一种特殊的锁,允许多个线程同时读取共享资源,但在写操作时需要独占访问。读写锁适用于读多写少的场景,可以提高并发性能。

3.2 读写锁的相关函数详解

3.2.1 pthread_rwlock_init

函数原型:

int pthread_rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr);

功能:
初始化读写锁。

参数:

  • rwlock:指向读写锁的指针。

  • attr:读写锁的属性,通常设置为NULL,表示使用默认属性。

返回值:

  • 成功返回0,失败返回错误码。

示例:

pthread_rwlock_t rwlock;
pthread_rwlock_init(&rwlock, NULL);
3.2.2 pthread_rwlock_destroy

函数原型:

int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);

功能:
销毁读写锁。

参数:

  • rwlock:指向读写锁的指针。

返回值:

  • 成功返回0,失败返回错误码。

示例:

pthread_rwlock_destroy(&rwlock);
3.2.3 pthread_rwlock_rdlock

函数原型:

int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);

功能:
获取读锁。

参数:

  • rwlock:指向读写锁的指针。

返回值:

  • 成功返回0,失败返回错误码。

示例:

pthread_rwlock_rdlock(&rwlock);
3.2.4 pthread_rwlock_wrlock

函数原型:

int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);

功能:
获取写锁。

参数:

  • rwlock:指向读写锁的指针。

返回值:

  • 成功返回0,失败返回错误码。

示例:

pthread_rwlock_wrlock(&rwlock);
3.2.5 pthread_rwlock_unlock

函数原型:

int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);

功能:
释放读写锁。

参数:

  • rwlock:指向读写锁的指针。

返回值:

  • 成功返回0,失败返回错误码。

示例:

pthread_rwlock_unlock(&rwlock);

3.3 读写锁的使用示例

下面是一个简单的示例,演示了如何使用读写锁来保护共享资源。

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>pthread_rwlock_t rwlock;
int shared_data = 0;void* reader_func(void* arg) {pthread_rwlock_rdlock(&rwlock);printf("Reader: shared_data = %d\n", shared_data);pthread_rwlock_unlock(&rwlock);return NULL;
}void* writer_func(void* arg) {pthread_rwlock_wrlock(&rwlock);shared_data++;printf("Writer: shared_data = %d\n", shared_data);pthread_rwlock_unlock(&rwlock);return NULL;
}int main() {pthread_t readers[5], writers[2];pthread_rwlock_init(&rwlock, NULL);for (int i = 0; i < 5; i++) {pthread_create(&readers[i], NULL, reader_func, NULL);}for (int i = 0; i < 2; i++) {pthread_create(&writers[i], NULL, writer_func, NULL);}for (int i = 0; i < 5; i++) {pthread_join(readers[i], NULL);}for (int i = 0; i < 2; i++) {pthread_join(writers[i], NULL);}pthread_rwlock_destroy(&rwlock);return 0;
}

3.4 运行结果

Reader: shared_data = 0
Reader: shared_data = 0
Reader: shared_data = 0
Reader: shared_data = 0
Reader: shared_data = 0
Writer: shared_data = 1
Writer: shared_data = 2

3.5 代码解析

  • pthread_rwlock_rdlock(&rwlock):获取读锁,允许多个线程同时读取共享资源。

  • pthread_rwlock_wrlock(&rwlock):获取写锁,独占访问共享资源。

  • pthread_rwlock_unlock(&rwlock):释放读写锁。

读写锁出现的场景还是比较多的,尤其是当写少读多的时候,读写锁可以帮助我们提高并发效率

4. POSIX信号量

4.1 POSIX信号量的基本概念

POSIX信号量是一种用于线程同步的机制,可以用来控制对共享资源的访问。信号量有一个整数值,表示可用资源的数量。线程可以通过sem_waitsem_post来分别减少和增加信号量的值。

4.2 POSIX信号量的相关函数详解

4.2.1 sem_init

函数原型:

int sem_init(sem_t *sem, int pshared, unsigned int value);

功能:
初始化信号量。

参数:

  • sem:指向信号量的指针。

  • pshared:指定信号量的类型,0表示线程间共享,非0表示进程间共享。

  • value:信号量的初始值。

返回值:

  • 成功返回0,失败返回-1。

示例:

sem_t sem;
sem_init(&sem, 0, 0);
4.2.2 sem_destroy

函数原型:

int sem_destroy(sem_t *sem);

功能:
销毁信号量。

参数:

  • sem:指向信号量的指针。

返回值:

  • 成功返回0,失败返回-1。

示例:

sem_destroy(&sem);
4.2.3 sem_wait

函数原型:

int sem_wait(sem_t *sem);

功能:
减少信号量的值,如果信号量的值为0,则阻塞。

参数:

  • sem:指向信号量的指针。

返回值:

  • 成功返回0,失败返回-1。

示例:

sem_wait(&sem);
4.2.4 sem_post

函数原型:

int sem_post(sem_t *sem);

功能:
增加信号量的值,并唤醒等待的线程。

参数:

  • sem:指向信号量的指针。

返回值:

  • 成功返回0,失败返回-1。

示例:

sem_post(&sem);
4.2.5 sem_trywait

函数原型:

int sem_trywait(sem_t *sem);

功能:
尝试减少信号量的值,如果信号量的值为0,则立即返回错误。

参数:

  • sem:指向信号量的指针。

返回值:

  • 成功返回0,失败返回-1。

示例:

sem_trywait(&sem);
4.2.6 sem_getvalue

函数原型:

int sem_getvalue(sem_t *sem, int *sval);

功能:
获取信号量的当前值。

参数:

  • sem:指向信号量的指针。

  • sval:指向存储信号量值的整数的指针。

返回值:

  • 成功返回0,失败返回-1。

示例:

int value;
sem_getvalue(&sem, &value);

4.3 POSIX信号量的使用示例

下面是一个简单的示例,演示了如何使用POSIX信号量来同步两个线程的执行。

#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>sem_t sem;void* thread_func(void* arg) {printf("Thread waiting...\n");sem_wait(&sem);printf("Thread awakened!\n");return NULL;
}int main() {pthread_t tid;sem_init(&sem, 0, 0);pthread_create(&tid, NULL, thread_func, NULL);sleep(1);  // 模拟一些工作printf("Main thread signaling...\n");sem_post(&sem);pthread_join(tid, NULL);sem_destroy(&sem);return 0;
}

4.4 运行结果

Thread waiting...
Main thread signaling...
Thread awakened!

4.5 代码解析

  • sem_wait(&sem):减少信号量的值,如果信号量的值为0,则阻塞。

  • sem_post(&sem):增加信号量的值,并唤醒等待的线程。

我们在前面讲进程的时候就讲过信号量的知识了,这里基本没啥大的差别,关于POSIX信号量的使用,我们在下一章讲生产消费模型的时候也会再详细讲解的,这里大家先理解一下基本用法即可

5. 总结

本文详细讨论了Linux中线程同步的几种机制,包括条件变量、读写锁和POSIX信号量。通过简单的代码示例,我们演示了如何使用这些机制来同步多个线程的执行。在实际的多线程编程中,选择合适的同步机制非常重要,可以有效避免数据竞争、死锁等问题。

5.1 条件变量的适用场景

条件变量适用于需要等待某个条件成立的场景,通常与互斥锁一起使用。例如,生产者-消费者模型中的缓冲区满或空的情况。

5.2 读写锁的适用场景

读写锁适用于读多写少的场景,可以提高并发性能。例如,数据库系统中的读操作远多于写操作。

5.3 POSIX信号量的适用场景

POSIX信号量适用于需要控制对共享资源访问的场景。例如,限制同时访问某个资源的线程数量。

5.4 选择同步机制的考虑因素

在选择线程同步机制时,需要考虑以下因素:

  • 性能:不同的同步机制对性能的影响不同,需要根据具体场景选择最合适的机制。

  • 复杂性:某些同步机制的使用较为复杂,需要仔细设计和测试。

  • 可维护性:选择易于理解和维护的同步机制,可以减少代码的复杂性和出错的可能性。

总之,线程的同步是确保线程安全很重要的一步,今天我们讲解了确保线程同步机制的重要的几个方面,关于这几个方面的知识点的应用在下一篇生成消费模型还会仔细讲解一遍

本篇笔记:

感谢各位大佬观看,创作不易,还请各位大佬点赞支持一下!!!

相关文章:

【Linux探索学习】第三十一弹——线程互斥与同步(下):深入理解确保线程安全的机制

线程互斥与同步&#xff08;上&#xff09;&#xff1a;【Linux探索学习】第三十弹——线程互斥与同步&#xff08;上&#xff09;&#xff1a;深入理解线程保证安全的机制-CSDN博客 Linux探索学习&#xff1a; https://blog.csdn.net/2301_80220607/category_12805278.html?…...

博客系统完整开发流程

前言 通过前⾯课程的学习, 我们掌握了Spring框架和MyBatis的基本使用, 并完成了图书管理系统的常规功能开发, 接下来我们系统的从0到1完成⼀个项⽬的开发. 企业开发的流程 1. 需求评审(产品经理(PM)会和运营(想口号),UI,测试,开发等沟通) ,会涉及到背景/目标/怎么做,可能会有多…...

【C++】面试常问八股

5、内存管理 野指针 野指针指的是未进行初始化或未清零的指针&#xff0c;不是NULL指针野指针产生原因及解决方案&#xff1a; 指针变量未初始化&#xff1a;指针变量定义时若未初始化&#xff0c;则其指向的地址是随机的&#xff0c;不为NULL&#xff1b;定义时初始化为NULL…...

自定义提交按钮触发avue-form绑定的submit事件

场景 使用avue-form时&#xff0c;提交按钮会绑定至form区域下方&#xff0c;如果想自定义按钮位置&#xff0c;需要通过dialog的footer位置进行编写&#xff0c;例如&#xff1a; <avue-form ref"form" v-model"dataInfo" :option"dataInfoOpti…...

HarmonyOS 无线调试

下载sdk 找到hdc位置> C:\Users\27638\AppData\Local\OpenHarmony\Sdk\14\toolchains 不要去DevEco Studio的窗口不知道为什么调不动 hdc tconn IP:PORT...

Android之APP更新(通过接口更新)

文章目录 前言一、效果图二、实现步骤1.AndroidManifest权限申请2.activity实现3.有版本更新弹框UpdateappUtilDialog4.下载弹框DownloadAppUtils5.弹框背景图 总结 前言 对于做Android的朋友来说&#xff0c;APP更新功能再常见不过了&#xff0c;因为平台更新审核时间较长&am…...

二、大模型微调技术栈全解析

大模型微调技术栈全解析&#xff1a;从微调方法到算力支撑 在大模型的领域中&#xff0c;微调&#xff08;Fine-tuning&#xff09;就像是为模型量身定制的高级裁缝服务&#xff0c;能够让通用的大模型更好地适应特定的任务和场景。而要完成这项精细的工作&#xff0c;需要一整…...

设置 C++ 开发环境

设置 C++ 开发环境 C++ 是一种通用编程语言,现在广泛用于竞争性编程。它具有命令式、面向对象的和通用编程功能。 C++ 可以在许多平台上运行,如 Windows、Linux、Unix、Mac 等。在我们开始使用 C++ 编程之前。我们需要在本地计算机上设置一个环境,以便成功编译和运行我们的…...

计算机基础知识

1、RAM和ROM RAM&#xff1a;随机存取存储器&#xff0c;也叫做主存。是与CPU直接交换数据的内部存储器。这种存储器在断电时将丢失其数据&#xff0c;故主要用于短时间使用的程序。 ROM&#xff1a;即只读存储&#xff0c;是一种只能读出事先所存数据的固态半导体存储器 2、…...

蓝桥杯——按键

一&#xff1a;按键得原理图 二&#xff1a;按键的代码配置 step1 按键原理图对应引脚配置为输入状态 step2 在GPIO中将对应引脚设置为上拉模式 step3 在fun.c中写按键扫描函数 写完后的扫描函数需放在主函数中不断扫描 扫描函数主要通过两个定义变量的值来判断&#xf…...

Zemax OpticStudio 中的扩散器建模

在 Zemax OpticStudio 中构建漫射器涉及创建散射或漫射光的表面或物体。以下是有关如何在 Zemax OpticStudio 中创建漫射器的一般指南&#xff1a; 转到非序列模式 (NSC) 选项卡。NSC 对于模拟与物体而非表面相互作用的非序列射线很有用。 在需要散光器的位置创建新对象。对象…...

网络安全防御:蓝队重保备战与应急溯源深度解析

课程目标 本课程旨在培养专业的网络安全蓝队成员&#xff0c;通过系统化的学习和实战演练&#xff0c;使学员能够掌握网络安全防御的核心技能&#xff0c;包括资产测绘、应急响应、系统安全应急溯源分析、网络层溯源分析以及综合攻防演练等。学员将能够熟练运用各种工具和技术…...

MySQL 和 Elasticsearch 之间的数据同步

MySQL 和 Elasticsearch 之间的数据同步是常见的需求&#xff0c;通常用于将结构化数据从关系型数据库同步到 Elasticsearch 以实现高效的全文搜索、聚合分析和实时查询。以下是几种常用的同步方案及其实现方法&#xff1a; 1. 应用层双写&#xff08;双写模式&#xff09; 原…...

【深度学习】矩阵的核心问题解析

一、基础问题 1. 如何实现两个矩阵的乘法&#xff1f; 问题描述&#xff1a;给定两个矩阵 A A A和 B B B&#xff0c;编写代码实现矩阵乘法。 解法&#xff1a; 使用三重循环实现标准矩阵乘法。 或者使用 NumPy 的 dot 方法进行高效计算。 def matrix_multiply(A, B):m, n …...

汽车开放系统架构(AUTOSAR)中运行时环境(RTE)生成过程剖析

一、引言 在当今高度智能化的汽车电子领域&#xff0c;软件系统的复杂性呈指数级增长。为了应对这一挑战&#xff0c;汽车开放系统架构&#xff08;AUTOSAR&#xff09;应运而生&#xff0c;它为汽车电子软件开发提供了标准化的分层架构和开发方法。其中&#xff0c;运行时环境…...

VC++零基础入门之系列教程 【附录E MFC快速参考指南】

附录E MFC快速参考指南 E.1 创建窗口 使用M F C CWnd wnd; W n d . C r e a t e E x ( E xSt y l e , C l a s s N a m e , Wi n d o w N a m e , S t y l e , x , y, Wi d t h , H e i g h t , P a r e n t , M e n u , P a r a m ) ; 使用A P I HWND hwnd=::CreateWi n d …...

Holoens2开发报错记录02_通过主机获取彩色和深度数据流常见错误

01.E1696 E1696 无法打开源文件 “stdio.h” 解决方法&#xff1a; 更新一下SDK 1&#xff09;打开Visual Studio Installer&#xff0c;点击修改 2&#xff09;安装详细信息中自己系统对应的SDK&#xff0c;点击修改即可 02.WinError 10060 方法来源 解决方法&#xff1a…...

粉色和紫色渐变壁纸怎么设计?

粉色和紫色的渐变壁纸设计可以打造极为浪漫的氛围&#xff0c;这两种颜色的搭配极具梦幻感与浪漫气息&#xff0c;常被用于各种浪漫主题的设计之中。以下是关于粉色和紫色渐变壁纸的设计方法&#xff1a; 一、渐变方向设计 横向渐变&#xff1a;从画面左侧的粉色过渡到右侧的紫…...

maven Problem shading JAR的几个解决方案

1 现象 Error creating shaded jar: Problem shading JAR &#xff1a;xxxxxx.jar entry META-INF/versions/11/com/fasterxml/jackson/core/io/doubleparser/BigSignificand.class: java.lang.IllegalArgumentException -> [Help 1] 2 原因 这个问题通常是由于 maven-s…...

前缀和代码解析

前缀和是指数组一定范围的数的总和,常见的有两种,一维和二维,我会用两道题来分别解析 一维 DP34 【模板】前缀和 题目: 题目解析: 暴力解法 直接遍历数组,遍历到下标为 l 时,开始进行相加,直到遍历到下标为 r ,最后返回总和.这样做的时间复杂度为: O(n) public class Main …...

CaffeineCache自定义缓存时间

文章目录 1、POM文件依赖2、声明缓存3、缓存使用4、测试缓存5、自定义缓存过期时间6、测试自定义超时时间 1、POM文件依赖 <dependency><groupId>com.github.ben-manes.caffeine</groupId><artifactId>caffeine</artifactId><version>3.1…...

keil中出现Error_Handler错误的解决方法

这个错误表明在代码中使用了 Error_Handler 函数但未定义。以下是完整的修复方案&#xff1a; 步骤 1&#xff1a;在 main.h 中添加函数声明 /* main.h */ void Error_Handler(void);步骤 2&#xff1a;在 main.c 中完善错误处理函数 /* main.c */ void Error_Handler(void) …...

low rank decomposition如何用于矩阵的分解

1. 什么是矩阵分解和低秩分解 矩阵分解是将一个矩阵表示为若干结构更简单或具有特定性质的矩阵的组合或乘积的过程。低秩分解&#xff08;Low Rank Decomposition&#xff09;是其中一种方法&#xff0c;旨在将原矩阵近似为两个或多个秩较低的矩阵的乘积&#xff0c;从而降低复…...

Cesium@1.126.0,创建3D瓦片,修改样式

第一步&#xff1a;添加3D建筑 Cesium.createOsmBuildingsAsync()这是一个异步方法&#xff0c;所以要写在一个异步函数里 创建一个函数 const create3DBuilding async (viewer) > {try {// 添加3D建筑const tileset await Cesium.createOsmBuildingsAsync();viewer.scen…...

MFC学习笔记-1

一、编辑框和按钮 //.h文件private:CString str;//给窗口类加了一个变量&#xff08;定义一个成员变量&#xff09;&#xff0c;关联到IDC_EDIT1中&#xff08;要在实现中关联&#xff0c;源文件文件夹中&#xff09;CString str2;//接收button2&#xff0c;和IDC_EDIT2绑定 p…...

Bugku CTF CRYPTO

Bugku CTF CRYPTO 文章目录 Bugku CTF CRYPTO聪明的小羊ok[-<>]散乱的密文.!? 聪明的小羊 描 述: 一只小羊翻过了2个栅栏 fa{fe13f590lg6d46d0d0} 分 析&#xff1a;栅栏密码&#xff0c;分2栏&#xff0c;一个栏里有11个 ①手动解密 f a { f e 1 3 f 5 9 0 l g 6 d 4 …...

Leetcode2502:设计内存分配器

题目描述&#xff1a; 给你一个整数 n &#xff0c;表示下标从 0 开始的内存数组的大小。所有内存单元开始都是空闲的。 请你设计一个具备以下功能的内存分配器&#xff1a; 分配 一块大小为 size 的连续空闲内存单元并赋 id mID 。释放 给定 id mID 对应的所有内存单元。 …...

BERT模型详解及代码复现

架构设计 BERT模型的架构设计是其成功的关键之一,它巧妙地融合了Transformer架构的优势,并针对自然语言处理任务进行了优化。具体来说,BERT的架构主要由三个模块组成: Embedding模块 :负责将输入的文本转换为模型可处理的向量表示。该模块由三种Embedding组成: Token Em…...

面试中自己挖的一些坑

一些面试的细节深度持续更新。。。 1. 这里有4题&#xff0c;单独写成了博客2. 经典的八股文之一 (ArrayList扩容原理)1.博主的回答2.面试官问的一些细节 3.经典的八股文之一 (HashMap扩容原理)1.博主的回答2.面试官问的一些细节 4.SpringBoot的启动原理1. 博主回答2. 面试官问…...

二、环 Ring

文章目录 一、环的定义二、环的分类与变种1、交换环2、含单位元的环3、零环4、非交换环5、整环6、域 三、环的性质与应用四、环与群和域的对比 一、环的定义 一个集合 R 被称为一个环&#xff0c;如果它满足以下条件&#xff1a; 对于 加法 满足&#xff1a; 闭合性&#xff1…...

Python图像处理入门:如何打开图像文件及常见格式

神经网络中的图像处理是一个非常重要的环节&#xff0c;尤其是在计算机视觉领域。作为一名新手&#xff0c;你可能会遇到一个常见的挑战——如何在 Python 中打开并理解图像文件。在本篇文章中&#xff0c;我们将介绍几种常见的图像文件格式&#xff0c;并讲解如何使用 Python …...

银河麒麟高级服务器操作系统在线调整/pro/{PID}/limits文件中nofile的软限制和硬限制参数值操作方法

银河麒麟高级服务器操作系统在线调整/pro/{PID}/limits文件中nofile的软限制和硬限制参数值操作方法 一 系统环境二 使用场景三 操作步骤 一 系统环境 [rootlocalhost ~]# nkvers ############## Kylin Linux Version ################# Release: Kylin Linux Advanced Server…...

网络运维学习笔记 018 HCIA-Datacom综合实验02

文章目录 综合实验2sw3&#xff1a;sw4&#xff1a;gw&#xff1a;core1&#xff08;sw1&#xff09;&#xff1a;core2&#xff08;sw2&#xff09;&#xff1a;ISP 综合实验2 sw3&#xff1a; vlan 2 stp mode stp int e0/0/1 port link-type trunk port trunk allow-pass v…...

深度学习进阶:构建多层神经网络

在上一篇文章中&#xff0c;我们从零开始构建了一个简单的两层神经网络&#xff0c;并通过异或问题&#xff08;XOR&#xff09;展示了神经网络的强大能力。今天&#xff0c;我们将进一步深入&#xff0c;构建一个更复杂的多层神经网络&#xff0c;并引入更多高级概念&#xff…...

高斯消元法

前置数学知识 n元线性方程是具有如下形式的方程&#xff1a; a 1 x 1 a 2 x 2 a 3 x 3 … a n x n b a_1x_1a_2x_2a_3x_3…a_nx_n b a1​x1​a2​x2​a3​x3​…an​xn​b 其中&#xff0c; a 1 , a 2 , . . . a_1,a_2,... a1​,a2​,...以及常数项 b b b均为已知的实数…...

ubuntu 安全策略(等保)

windows 三个帐号屏保设置组策略,密码超时次数/审计记录&#xff1b; linux 应具有登录失败处理功能&#xff0c;应配置并启用结束会话、限制非法登录次数和当登录连接超时自动退出等相关措施。 1、在系统中新建测试用户&#xff0c;使用此用户登录时多次输入错误密码&…...

计算机毕业设计SpringBoot+Vue.js购物推荐系统网站(源码+文档+PPT+讲解)

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…...

QT线程同步

文章目录 前言1. 使用互斥锁&#xff08;QMutex&#xff09;2.使用QMutexLocker便利类3. 使用读写锁&#xff08;QReadWriteLock&#xff09;4.QReadLocker便利类和QWriteLocker便利类对QReadWriteLock进行加解锁5. 使用信号量&#xff08;QSemaphore&#xff09;6. 使用条件变…...

何为第一二三产业?

第一、第二、第三产业的分类是经济学中对经济活动的划分方式&#xff0c;起源于20世纪30年代经济学家费希尔和克拉克的理论。以下是具体说明&#xff1a; 第一产业&#xff08;Primary Sector&#xff09; 定义&#xff1a;直接利用自然资源进行生产活动的行业。 核心领域&…...

Spring 面试题

Autowired和Resource两个注解的区别 Autowired&#xff1a; 是Spring框架的注解&#xff0c;用于依赖注入。 默认按照类型&#xff08;byType&#xff09;注入&#xff0c;如果存在多个相同类型的Bean&#xff0c;则会报错。 可以通过Qualifier指定具体的Bean名称。 如果没有匹…...

Linux设备驱动开发-SPI驱动开发详解(包含设备树处理详细过程)

基础知识及 SPI 相关结构体介绍 引脚&#xff1a;MISO&#xff08;master 输入&#xff0c;slave 输出&#xff09;&#xff0c;MOSI&#xff08;master 输出&#xff0c;slave 输入&#xff09;&#xff0c;片选引脚&#xff0c;SCK&#xff08;时钟&#xff09; 控制寄存器&…...

物联网平台建设方案一

系统概述 构建物联网全域支撑服务能力&#xff0c;为实现学院涵盖物联网设备的全面感知、全域互联、全程智控、全域数字基底、全过程统筹管理奠定基础&#xff0c;为打造智能化提供坚实后台基石。 物联网平台向下接入各种传感器、终端和网关&#xff0c;向上通过开放的实施分…...

java23种设计模式-桥接模式

桥接模式&#xff08;Bridge Pattern&#xff09;学习笔记 &#x1f31f; 定义 桥接模式属于结构型设计模式&#xff0c;将抽象部分与实现部分分离&#xff0c;使它们可以独立变化。通过组合代替继承的方式&#xff0c;解决多维度的扩展问题&#xff0c;防止类爆炸。 &#x…...

springboot实现文件上传到华为云的obs

一、前言 有时在项目中需要使用一些存储系统来存储文件&#xff0c;那么当项目要接入obs作为存储系统时&#xff0c;就会利用obs来进行文件的上传下载&#xff0c;具体实现如下。 二、如何通过obs实现文件的上传下载&#xff1f; 1.添加相关的obs的maven依赖。 <dependency…...

【红队利器】单文件一键结束火绒6.0

关于我们 4SecNet 团队专注于网络安全攻防研究&#xff0c;目前团队成员分布在国内多家顶级安全厂商的核心部门&#xff0c;包括安全研究领域、攻防实验室等&#xff0c;汇聚了行业内的顶尖技术力量。团队在病毒木马逆向分析、APT 追踪、破解技术、漏洞分析、红队工具开发等多个…...

DeepSeek 助力 Vue 开发:打造丝滑的滚动动画(Scroll Animations)

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享一篇文章&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目录 Deep…...

Compose 动画,让页面动起来

Compose 动画&#xff0c;让页面动起来 概述高级别动画APIAnimatedVisibilityMutableTransitionStateModifier.animateEnterExit自定义Enter/Exit动画 AnimatedContentContentTransform自定义动画SizeTranstion定义大小动画定义子元素动画自定义Enter/Exit动画 CrossfadeModifi…...

Windows CMD 命令大全(Complete List of Windows CMD Commands)

Windows CMD 命令大全&#xff1a; Windows CMD 是 Windows 系统内置的命令行工具&#xff0c;用于执行各种命令和管理任务。 称为Command Prompt。它提供了一个通过键入命令来与计算机系统进行交互的方式&#xff0c;类似于早期的DOS操作系统。以下是 CMD 的基础知识和常用命…...

DeepSeek在MATLAB上的部署与应用

在科技飞速发展的当下&#xff0c;人工智能与编程语言的融合不断拓展着创新边界。DeepSeek作为一款备受瞩目的大语言模型&#xff0c;其在自然语言处理领域展现出强大的能力。而MATLAB&#xff0c;作为科学计算和工程领域广泛应用的专业软件&#xff0c;拥有丰富的工具包和高效…...

IP代理在网络数据挖掘中的关键作用(AI大模型数据采集版)

在当今人工智能飞速发展的时代&#xff0c;AI大模型的训练需要海量且多样化的数据。然而&#xff0c;在数据采集过程中&#xff0c;常常面临诸多挑战&#xff0c;而IP代理在其中发挥着至关重要的作用。 数据采集的多样性是影响AI大模型性能的关键因素。如果数据来源单一&#x…...