线程与多线程(二)
线程与多线程(二)
- 一、线程互斥
- 1、相关概念
- 二、互斥锁
- 1、介绍
- 2、使用场景
- 3、初始化
- (1)函数
- (2)概念
- 4、销毁
- (1)函数
- (2)概念
- 5、加锁
- (1)函数
- (2)概念
- 6、解锁
- (1)函数
- (2)概念
- 7、示例代码
- 8、运行结果
- 三、安全
- 1、线程安全
- 2、重入
- 3、常见的线程不安全的情况
- 四、死锁
- 1、概念
- 2、产生的必要条件
- 3、避免方法
- 五、条件变量
- 1、背景概念
- 2、初始化与销毁
- 3、等待
- (1)函数
- (2)参数意义
- (3)互斥锁的作用
- 4、唤醒
- (1)函数
- (2)概念
- 5、示例代码
- 6、运行结果
- 六、生产者消费者模型
- 1、概念
- 2、示意图
- 3、优点
- 4、环形队列
- (1)示意图
- (2)说明
- 七、POSIX信号量
- 1、概念
- 2、初始化
- (1)函数
- (2)概念
- 3、销毁
- (1)函数
- (2)概念
- 4、等待
- (1)函数
- (2)概念
- 5、发布
- (1)函数
- (2)概念
- 八、单例模式
- 1、概念
- 2、实现方式
- (1)饿汉模式
- (2)懒汉模式
- 九、其他常见的锁
本文为多线程相关的内容,线程相关的内容参见线程与多线程(一)。
一、线程互斥
1、相关概念
- 临界资源(互斥资源)为多线程执行流共享的资源。
- 临界区为每个线程内部,访问临界资源的程序段(代码)。
- 互斥为任何时刻都保证有且只有一个执行流进入临界区访问临界资源,通常对临界资源起保护作用。
- 原子性为所进行的操作不会被任何调度机制打断。该操作只有两态,即完成态和未完成态,而没有中间状态。
二、互斥锁
1、介绍
- 使用互斥锁的本质是用时间来换取安全,表现为线程对于临界区代码串行执行,原则上是尽量的要保证临界区代码越少越好。
- 因为锁本身就是共享资源,所以,申请互斥锁和释放互斥锁的操作被设计成原子性操作。
- 在纯互斥环境下,如果锁分配不够合理就容易导致其他线程的饥饿问题。
- 在临界区中,线程可以被切换,但在线程被切换出去的时候,其是持有锁被切换的。在这期间没有谁能进入该互斥锁所锁定的临界区去访问临界资源。
- 持有互斥锁的线程访问临界区的过程,对于其他线程来说是原子的。
2、使用场景

3、初始化
(1)函数

(2)概念
- pthread_mutex_init函数将使用attr指定的属性初始化mutex引用的互斥锁。如果attr为NULL,则使用默认的互斥属性,其效果与传递默认互斥属性对象的地址的效果相同。
- 只有互斥锁本身可用于执行同步。在调用pthread_mutex_lock函数、pthread_mutex_trylock函数、pthread_mutex_unlock函数和pthread_mutex_destroy函数时引用互斥锁副本的结果是未定义的。
- 在默认互斥锁属性适用的情况下,宏PTHREAD_MUTEX_INITIALIZER可用于初始化静态分配的互斥锁。该效果等同于通过调用pthread_mutex_init函数,并将参数attr指定为NULL进行动态初始化,但不执行错误检查。
- 尝试初始化已初始化的互斥锁的行为是未定义的。
- 初始化成功后,互斥锁的状态将被初始化且为解锁状态。
4、销毁
(1)函数

(2)概念
- pthread_mutex_destroy函数的作用为将mutex引用的互斥对象销毁。
- 互斥对象实际上会变成未初始化。即pthread_mutex_destroy函数会将mutex引用的对象设置为无效值。
- 被销毁的互斥对象可以使用pthread_mutex_init函数重新初始化。而在对象被销毁后,以其他方式引用该对象的结果是未定义的。
- 销毁已解锁且初始化的互斥锁是安全的,而试图销毁锁定的互斥锁会导致未定义的行为。
- 使用 PTHREAD_ MUTEX_ INITIALIZER 初始化的互斥锁不需要调用pthread_mutex_destroy函数销毁。
5、加锁
(1)函数

(2)概念
- mutex引用的互斥对象可通过调用pthread_mutex_lock函数来锁定。如果该互斥锁已被锁定,则调用的线程会进行阻塞等待,直到互斥锁可用。此操作(申请锁)成功将返回处于锁定状态的互斥对象,调用线程作为其所有者。
- 申请互斥锁成功后,尝试重新锁定互斥锁会导致死锁。如果一个线程试图解锁它没有锁定的互斥锁或处于解锁状态的互斥锁,则会导致未定义的行为,返回错误。
- pthread_mutex_trylock函数等效于pthread_mutex_lock函数,但如果mutex引用的互斥对象当前被锁定(已被任何线程,包括当前线程申请成功),则调用会立即返回。
6、解锁
(1)函数

(2)概念
- pthread_mutex_unlock函数释放mutex引用的互斥对象。而互斥锁的释放方式取决于互斥锁的类型属性。
- 如果在调用pthread_mutex_unlock函数时,mutex引用的互斥对象上有线程被阻塞,则当互斥对象可用时,调度策略应确定哪个线程应获取该互斥对象。
- 如果一个信号被传递给等待互斥锁的线程,那么在信号处理程序返回时,线程应继续等待之前等待的互斥锁,就像该线程没有被中断一样。
7、示例代码
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
int count = 0;
class threadData
{
public:threadData(int number/*, pthread_mutex_t *lock*/)//:_lock(lock){_threadName = "thread-" + to_string(number);}string _threadName;//pthread_mutex_t *_lock;
};void *Routine(void *args)
{threadData *td = static_cast<threadData*>(args);while(true){pthread_mutex_lock(&lock);//pthread_mutex_lock(td->_lock);cout << td->_threadName << ", counting: " << count++ << endl;pthread_mutex_unlock(&lock);//pthread_mutex_unlock(td->_lock);if(count >= 6)break;sleep(1);}cout << td->_threadName << " quit" << endl;return nullptr;
}int main()
{vector<pthread_t> tids;vector<threadData*> tds;// pthread_mutex_t lock;// pthread_mutex_init(&lock, nullptr);for(int i = 0; i < 4; ++i){pthread_t tid;threadData *td = new threadData(i/*, &lock*/);tds.push_back(td);pthread_create(&tid, nullptr, Routine, td);tids.push_back(tid);}for(auto tid : tids){pthread_join(tid, nullptr);}cout << "main thread wait thread over" << endl;for(auto td : tds){delete td;}cout << "main thread delete thread over" << endl;//pthread_mutex_destroy(&lock);return 0;
}
8、运行结果

三、安全
1、线程安全
- 如果线程是安全的,则多个线程并发执行同一段代码时,不会出现不同的结果。
- 在没有锁保护的情况下,对全局变量或者静态变量进行操作,会出现线程安全问题。
2、重入
- 重入为同一个函数被不同的执行流调用时,当前一个流程还没有执行完,就有其他的执行流再次进入。
- 一个函数在重入的情况下,运行结果不会出现任何不同或者任何问题,则该函数为可重入函数。否则则为不可重入函数。
3、常见的线程不安全的情况
- 不保护共享变量的函数。
- 函数状态随着被调用,状态发生变化的函数。
- 返回指向静态变量指针的函数。
- 调用线程不安全函数的函数。
四、死锁
1、概念
- 两个或两个以上的线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时系统处于死锁状态或系统产生了死锁。这些永远在互相等待的线程为死锁线程。
- 在死锁情况下,所占用的资源或者需要它们进行某种合作的其它线程会相继陷入死锁,最终可能导致整个系统处于瘫痪状态。
2、产生的必要条件
- 互斥条件:一个资源每次只能被一个执行流使用。这是产生死锁的前提。
- 请求与保持条件:一个执行流因请求资源而阻塞时,对已获得的资源保持不放。这是产生死锁的原则。
- 不剥夺条件:一个执行流已获得的资源,在末使用完之前,不能强行剥夺。这是产生死锁的原则。
- 循环等待条件:若干执行流之间形成一种头尾相接的循环等待资源的关系。这是产生死锁的重要条件。
3、避免方法
- 破坏四个必要条件。
- 加锁的顺序一致。
- 避免锁未释放的场景。
- 资源一次性分配。
五、条件变量
1、背景概念
- 同步:在保证数据安全的前提下,让线程能够按照某种特定的顺序访问临界资源,从而有效避免饥饿问题。
- 竞态条件:因为时序问题导致程序异常。
- 条件变量是一种线程同步的基本机制,用于线程之间发信号通知和等待。 它通常和互斥锁一起使用,以防止竞态条件和确保线程安全。即条件变量必须依赖于锁的使用。
- 条件变量的优点是可以以原子方式阻塞线程,直到某个特定条件为真为止。
2、初始化与销毁

3、等待
(1)函数

(2)参数意义
- 参数cond表示调用该函数的线程要在这个条件变量上等待。
- 参数mutex表示当线程申请不到mutex时,在条件变量cond下等待。
- 在等待时,如果不能申请到条件变量,则会释放锁mutex。
(3)互斥锁的作用
- 条件等待是线程间同步的一种手段,如果只有一个线程,条件不满足,会一直等下去,所以必须要有一个线程通过某些操作改变共享变量,使原先不满足的条件变得满足,并且友好的通知等待在条件变量上的线程。
- 条件不会无缘无故的突然变得满足,这必然会牵扯到共享数据的变化。所以,需要用互斥锁来保护,没有
互斥锁就无法安全的获取和修改共享数据。
4、唤醒
(1)函数

(2)概念
- pthread_cond_broadcast函数可解除当前阻塞在指定条件变量cond上的所有线程。
- 如果在cond上有任何线程被阻塞,pthread_cond_signal函数可解除当前阻塞在指定条件变量cond上的至少一个线程。
- 如果当前没有线程阻塞在条件变量cond上,则pthread_cond_broadcast和pthread_cond_signal函数将无效。
5、示例代码
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int cnt = 0;void *Rountine(void *args)
{pthread_detach(pthread_self());uint64_t number = (uint64_t)args;cout << "thread " << number << " created" << endl;while(true){pthread_mutex_lock(&lock);//此处可加判断语句,不满足再在条件变量下等待pthread_cond_wait(&cond, &lock);cout << "thread " << number << " count, cnt = " << cnt++ << endl;pthread_mutex_unlock(&lock);}
}int main()
{for(uint64_t i = 0; i < 4; ++i){pthread_t tid;pthread_create(&tid, nullptr, Rountine, (void*)i);usleep(1000);}while(true){sleep(2);//pthread_cond_signal(&cond);//cout << "main thread open one cond's" << endl;pthread_cond_broadcast(&cond);cout << "main thread open all cond's" << endl;}return 0;
}
6、运行结果

- 释放pthread_cond_signal以及下一行的注释,注释pthread_cond_broadcast以及下一行

六、生产者消费者模型
1、概念
- 生产者消费者模式就是通过一个容器来解决生产者和消费者的强耦合问题。
- 生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯。所以,生产者生产完数据之后不用等待消费者处理,而是直接扔给阻塞队列;消费者不找生产者要数据,而是直接从阻塞队列里取。
- 阻塞队列相当于一个缓冲区,平衡生产者和消费者的处理能力和用来给生产者和消费者解耦。
- 生产者和生产者之间是互斥关系、消费者和消费者之间是互斥关系、生产者和消费者之间是互斥且同步关系。
- 模型包括两种角色,生产者和消费者。
- 模型需要一个交易场所,即特定结构的内存空间。
2、示意图

3、优点
- 解耦
- 支持并发
- 支持忙闲不均
4、环形队列
(1)示意图

(2)说明
- 当环形队列满和空时,head和tail指向的是同一个位置。此时只能一方进行访问,当队列空时,生产者进行访问;当队列满时,消费者进行访问。
- 消费者不能超过生产者,生产者不能超过消费者一个环形队列的长度
七、POSIX信号量
1、概念
- 信号量是一个计数器,用于限制对共享资源的访问数量。
- 当多个线程或进程需要访问共享资源时,它们会先尝试获取信号量。如果信号量的值大于0,则允许一个线程或进程获取信号量并访问共享资源,然后将信号量的值减1。否则则会等待。
- 信号量把判断资源是否就绪放在了临界区之外,当申请信号量时,其实间接得在判断资源是否就绪。
2、初始化
(1)函数

(2)概念
- sem_init函数的作用为在sem指向的地址初始化未命名的信号量。
- value参数指定信号量的初始值。
- pshared参数指示此信号量是在进程的线程之间共享,还是在进程之间共享。
- 如果pshared的值为0,则信号量在进程的线程之间共享,并且应该位于所有线程可见的某个地址。如全局变量或在堆上动态分配的变量。
- 如果pshared为非零,则信号量在进程之间共享,并且应该位于共享内存区域中。任何可以访问共享内存区域的进程都可以使用sem_post、sem_wait等对信号量进行操作。
- 初始化已初始化的信号量的行为是未定义。
3、销毁
(1)函数

(2)概念
- sem_destroy函数的作用为销毁sem指向的地址处的未命名信号量。
- 只有由sem_init函数初始化的信号量才应该使用sem_destroy函数销毁。
- 销毁当前有其他进程或线程被阻塞的信号量(即其在sem_wait中)会产生未定义的行为。
- 使用已被销毁的信号量会产生未定义的结果,除非使用sem_init函数重新初始化该信号量。
4、等待
(1)函数

(2)概念
- sem_wait函数递减(锁定)sem指向的信号量。
- 如果信号量的值大于零,则递减继续进行,函数立即返回。
- 如果信号量当前的值为零,则调用会阻塞,直到可以执行递减(即信号量值升至零以上),或者信号处理程序中断该调用。
5、发布
(1)函数

(2)概念
- sem_post函数递增(解锁)sem指向的信号量。
- 如果信号量的值因此变得大于零,则sem_wait调用中阻塞的另一个进程或线程将被唤醒并继续进行锁定信号量的操作。
八、单例模式
1、概念
- 单例模式(Singleton Pattern)是一种设计模式。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
- 这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。
- 这个类提供了一种访问其唯一的对象的方式(全局访问点),可以直接访问,不需要实例化该类的对象。
2、实现方式
(1)饿汉模式
- 饿汉模式是一种设计模式,它在类加载时就完成了实例化操作。因此,在类加载时比较慢,但在获取对象时速度比较快。
- 它的优点是实现简单,线程安全。因为实例在类加载时就已经创建,所以不存在多线程下的同步问题。
- 它的缺点是在类加载时就完成了实例化,如果这个类在程序运行过程中从未被使用到,那么就会造成资源的浪费。
(2)懒汉模式
- 懒汉模式是一种在类加载时不进行实例化,只有在首次调用时才创建实例的设计模式。它的实现通常需要使用到同步机制来保证线程安全。
- 它的优点是可以延迟实例化,只有在实际需要时才会创建对象。
- 它的缺点是线程不安全,在多线程环境下,如果没有正确的同步机制,就可能会出现多个实例的情况。
九、其他常见的锁
- 悲观锁:在每次取数据时,总是担心数据会被其他线程修改。所以会在取数据前先加锁(读锁,写锁,行锁等),当其他线程想要访问数据时,会被阻塞挂起。
- 乐观锁:在每次取数据的时,总是乐观的认为数据不会被其他线程修改,因此不上锁。但是在更新数据前,会判断其他数据在更新前有没有对数据进行修改。主要采用两种方式,即版本号机制和CAS操作。
- CAS操作:当需要更新数据时,判断当前内存值和之前取得的值是否相等。如果相等则用新值更新。若不相等则失败,失败则重试,一般是一个自旋的过程,即不断重试。
- 读写锁:专门处理多读少写的情况,写时独占锁,读时共享锁,读锁的优先级比写锁高。写者之间是互斥竞争关系,写者与读者之间是互斥同步关系,读者之间是共享关系。
本文到这里就结束了,如有错误或者不清楚的地方欢迎评论或者私信
创作不易,如果觉得博主写得不错,请点赞、收藏加关注支持一下💕💕💕
相关文章:
线程与多线程(二)
线程与多线程(二) 一、线程互斥1、相关概念 二、互斥锁1、介绍2、使用场景3、初始化(1)函数(2)概念 4、销毁(1)函数(2)概念 5、加锁(1)…...
算法板子:欧拉函数——求一个数的欧拉函数、线性时间内求1~n所有数的欧拉函数
目录 1. 欧拉函数 (1)概念 (2)性质 (3)计算公式 2. 求一个数的欧拉函数 (1)模拟过程 (2)代码 3. 线性时间内求1~n所有数的欧拉函数——筛法求欧拉函…...
2024牛客暑期多校训练营8
文章目录 A. Haitang and GameE.Haitang and MathJ. Haitang and TriangleK. Haitang and Ava A. Haitang and Game 通过审题可以知道,最后的胜者和若干次操作后最多能增加的数的奇偶有关。 由于 a i a_i ai 较小,所以我们枚举每一个没出现过的 x …...
git的一些操作指令
一、git 提交规范 commit message subject : 空格 message 主体 feat: 新功能(feature)用于提交新功能。fix: 修复 bug用于提交 bug 修复。docs: 文档变更用于提交仅文档相关的修改。style: 代码风格变动(不影响代码逻辑&…...
【IT行业研究报告】Internet Technology
一、引言 随着信息技术的飞速发展,IT行业已成为全球经济的重要驱动力。从云计算、大数据、人工智能到物联网,IT技术正深刻改变着各行各业的生产方式、商业模式和人们的生活方式。本报告旨在深入分析IT行业的现状、发展趋势和挑战,探讨其在各…...
GLM大模型的机器翻译能力测试
背景介绍 最近想对GLM-4今年发布的几个大模型 glm-4-0520,glm-4-air以及glm-4-flash简单评测一下它们的机器翻译能力,由于这几个大模型的容量和训练数据都有区别,所以它们的翻译能力也是不同的。我们这里就分别选择一些有趣的,有…...
【硬件产品经理】汽车A样设计
目录 简介 制造方式 作者简介 简介 一般被称作原型样件(Prototype)。 主要是根据系统需求设计,实现基本功能和关键尺寸,用于基本功能的验证,用于初期产品软件调试和Hil台架测试(Hardware in Loop,硬件在环)的样机阶段。 也就说在设计初期,A样的主要目的可以划分…...
Ubuntu22.04系统中安装机器人操作系统ROS
在Ubuntu 22.04上安装ROS(Robot Operating System)的过程可以分为几个主要步骤。请注意,ROS有不同的版本(如ROS 1的Melodic、Noetic等,以及ROS 2的Foxy、Humble等),这些版本对Ubuntu的支持程度可…...
LeetCode54题:螺旋矩阵(原创)
【题目描述】 给你一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。 示例 1: 输入:matrix [[1,2,3],[4,5,6],[7,8,9]] 输出:[1,2,3,6,9,8,7,4,5]示例 2: 输入:mat…...
FPGA常见型号
FPGA(现场可编程门阵列)开发板种类繁多,涵盖了从入门级教育用途到高性能工业应用的广泛领域。以下是一些常见的 FPGA 开发板型号及其特点: 1. Xilinx(赛灵思)系列 Xilinx 是 FPGA 领域的领导者之一&#…...
【多模态大模型】FlashAttention in NeurIPS 2022
一、引言 论文: FlashAttention: Fast and Memory-Efficient Exact Attention with IO-Awareness 作者: Stanford University 代码: FlashAttention 特点: 该方法提出将Q、K、V拆分为若干小块,使执行注意力时不需要频…...
过滤器doFilter 方法
在Java EE中,过滤器的放行是指在过滤器的 doFilter 方法中调用 FilterChain 对象的 doFilter 方法,将请求传递给下一个过滤器或目标 servlet 进行处理。这个过程可以理解为过滤器的责任链传递。 过滤器的 doFilter 方法 在过滤器中,实现 Fil…...
WPF篇(9)-CheckBox复选框+RadioButton单选框+RepeatButton重复按钮
CheckBox复选框 CheckBox继承于ToggleButton,而ToggleButton继承于ButtonBase基类。 案例 前端代码 <StackPanel Orientation"Horizontal" HorizontalAlignment"Center" VerticalAlignment"Center"><TextBlock Text"…...
【机器学习基础】线性回归
【作者主页】Francek Chen 【专栏介绍】 ⌈ ⌈ ⌈Python机器学习 ⌋ ⌋ ⌋ 机器学习是一门人工智能的分支学科,通过算法和模型让计算机从数据中学习,进行模型训练和优化,做出预测、分类和决策支持。Python成为机器学习的首选语言,…...
java基础概念12-二维数组
一、二维数组的定义 二维数组可以被视为数组的数组,即每个元素都是一个数组。 二维数组的应用场景: 当我们需要把数据分组管理的时候,就需要用到二维数组。 二、二维数组的初始化 2-1、静态初始化 阿里巴巴规范手册: // 静态初始…...
56 锐键交换机开局
锐键交换机开局 一 锐键视图切换 1 Ruijie> 用户视图 2 Ruijie# 特权模式 3 Ruijie(config)# 全局配置模式 4 Ruijie(config-if-GigabitEthernet 1/1/1)# 接口配置模式 5 Ruijie(config)#show vlan 6 exit (退出) 7 enable(进入)...
VR虚拟展厅与传统实体展厅相比,有哪些优势?
视创云展虚拟展厅相比传统的实体展厅具有多方面的优势,主要体现在以下几个方面: 1、降低成本: 虚拟展厅无需租赁或建设物理空间,减少了场地、装修和维护等方面的开支。同时,参观者和参展商无需现场参观或布展&#x…...
Vue的事件处理、事件修饰符、键盘事件
目录 1. 事件处理基本使用2. 事件修饰符3. 键盘事件 1. 事件处理基本使用 使用v-on:xxx或xxx绑定事件,其中xxx是事件名,比如clickmethods中配置的函数,都是被Vue所管理的函数,this的指向是vm或组件实例对象 <!DOCTYPE html&g…...
c++单例实践
C单例实践 在日常开发中,虽然太多的单例调用会让代码的耦合度变高,但是例如日志类这种,单例模式就变得非常有。所以这篇文章为大家介绍static 关键字相关知识以及如何实现自己的C单例类。 static关键字 首先让我们请出今天的主角: static。…...
SQL注入实例(sqli-labs/less-9)
0、初始页面 1、爆库名 使用python脚本 def inject_database1(url):name for i in range(1, 20):low 32high 128mid (low high) // 2while low < high:payload "1 and if(ascii(substr(database(),%d,1)) > %d ,sleep(2),0)-- " % (i, mid)res {"…...
接口测试中缓存处理策略
在接口测试中,缓存处理策略是一个关键环节,直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性,避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明: 一、缓存处理的核…...
Docker 离线安装指南
参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性,不同版本的Docker对内核版本有不同要求。例如,Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本,Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...
【入坑系列】TiDB 强制索引在不同库下不生效问题
文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...
MODBUS TCP转CANopen 技术赋能高效协同作业
在现代工业自动化领域,MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步,这两种通讯协议也正在被逐步融合,形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...
Mac软件卸载指南,简单易懂!
刚和Adobe分手,它却总在Library里给你写"回忆录"?卸载的Final Cut Pro像电子幽灵般阴魂不散?总是会有残留文件,别慌!这份Mac软件卸载指南,将用最硬核的方式教你"数字分手术"࿰…...
Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)
引言:为什么 Eureka 依然是存量系统的核心? 尽管 Nacos 等新注册中心崛起,但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制,是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...
ip子接口配置及删除
配置永久生效的子接口,2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...
SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)
上一章用到了V2 的概念,其实 Fiori当中还有 V4,咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务),代理中间件(ui5-middleware-simpleproxy)-CSDN博客…...
多模态图像修复系统:基于深度学习的图片修复实现
多模态图像修复系统:基于深度学习的图片修复实现 1. 系统概述 本系统使用多模态大模型(Stable Diffusion Inpainting)实现图像修复功能,结合文本描述和图片输入,对指定区域进行内容修复。系统包含完整的数据处理、模型训练、推理部署流程。 import torch import numpy …...
【Linux】Linux安装并配置RabbitMQ
目录 1. 安装 Erlang 2. 安装 RabbitMQ 2.1.添加 RabbitMQ 仓库 2.2.安装 RabbitMQ 3.配置 3.1.启动和管理服务 4. 访问管理界面 5.安装问题 6.修改密码 7.修改端口 7.1.找到文件 7.2.修改文件 1. 安装 Erlang 由于 RabbitMQ 是用 Erlang 编写的,需要先安…...
