多线程和并发之线程

线程

前面讲到进程:为了并发执行任务(程序),现代操作系统才引进进程的概念
分析:

  • 创建开销问题:创建一个进程开销:大

    • 子进程需要拷贝父进程的整个地址空间
  • 通信开销问题:进程间的通信

    • 需要用第三方(如:内核
  • P1 -> copy -> 内核 -> copy -> P2

  • 进程间通信代价或者开销也是很大的。进程的地址空间是独立,要通信的话需要用第三方的空

  • 间。

于是,就有人提出能不能在 同一个(同一个进程内部)进程地址空间中进行任务的并发:线程/轻量级
进程

线程是一个比进程更小的活动单位。它是进程中的执行路径(执行分支),线程也是并发的一种形式。
进程内部可以存在多个线程,它并发执行,但是进程内部的所有的线程共享整个进程的地址空间
main 函数:进程的主线程

1 线程特点

  • 创建一个线程要比创建进程开销要小很多

    • 因为创建一个线程的话,不需要拷贝进程的地址空间
  • 实现线程间的通信会更加方便

    • 因为进程内部所有线程共享整个进程地址空间
  • 线程也是一个动态概念:

    • 线程(进程)状态图
      • 就绪态:ready
      • 运行态:running
      • 阻塞态:blocking

有了线程的概念之后

  • 系统的调度单位就从进程变为线程,资源的分配还是以进程为单位

线程是进程内部的一个指令的执行分支,多个线程就是多个指令序列并发执行。这些指令必须在函数
内部,线程的指令部分肯定是封装一个函数的内部的。这个函数,就称之为:线程函数,一个线程在创
建之后,要执行的指令全部封装在该函数内部,这个线程函数执行完毕之后,该线程的任务也就执行完

2 线程函数的原型

typedef void *(*start_routine_t)(void *);// 函数指针:指向一个返回值为void*且带有一个void*参数的函数
// 类型重定义:将一个函数指针类型重命名为start_routine_tvoid *my_thread(void *) // 咱自定义的线程函数:必须要符合返回值是void*且带有void*参数的一
//个函数
{// 执行线程需要执行的代码
}

3.Linux对线程的API的支持

Linux下采用的是POSIX Thread线程库。简称为:pthread

示例

#include <iostream>
#include <pthread.h>
#include <unistd.h>
using namespace std;string str = "你好,线程";
// 线程函数,表示线程启动之后第一时间会执行的函数
void *mythread(void *arg)
{cout  << "子线程:"  << str << endl;return nullptr;
}int main()
{// 创建线程// 第一次参数,用来存储线程的id号pthread_t tid;pthread_create(&tid, nullptr, mythread, nullptr);// 子线程先指向父线程再打印 保证子线程在父线程后面结束sleep(1);cout << "主线程:" << str << endl;return 0;
}

3.1 创建一个线程

pthread_create:创建一个线程(启动一个线程)

 PTHREAD_CREATE(3)                                  Linux Programmer's Manual     PTHREAD_CREATE(3)NAMEpthread_create - create a new threadSYNOPSIS#include <pthread.h>int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);/*@描述:创建一个新线程,启动一个线程@thread:指向的空间,用来存储线程的id号@attr:线程属性:用于指定新创建的线程的一些属性的。一般采用NULL,为默认属性@start_routine:线程函数,表示线程启动之后第一时间会执行的函数。也就是说新线程创建之后会指向start_routine函数内任务。@arg:参数,表示新线程要去start_routine执行任务,但是start_routine是一个函数。
start_routine是函数就可以有参数。所有arg实际上就是传给start_routine的参数的。@return:成功返回0,失败返回-1,同时errno被设置。*//*int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg){// 其他的代码// 创建线程去执行start_routinestart_routine(arg);如果线程创建成功return 0;否则就是:return -1;}*/

示例

#include <iostream>
#include <pthread.h>
#include <unistd.h>
using namespace std;string str = "你好,线程";
// 线程函数,表示线程启动之后第一时间会执行的函数
void *mythread(void *arg)
{cout  << "子线程:"  << str << endl;return nullptr;
}int main()
{// 创建线程// 第一次参数,用来存储线程的id号pthread_t tid;pthread_create(&tid, nullptr, mythread, nullptr);// 子线程先指向父线程再打印 保证子线程在父线程后面结束sleep(1);cout << "主线程:" << str << endl;return 0;
}

3.2 线程的退出

线程函数的退出(线程函数的返回)

 void *start_routine(void *arg){return nullptr; // 线程结束
}

在线程执行的任意时刻调用pthread_exit

 PTHREAD_EXIT(3)                                    Linux Programmer's Manual     PTHREAD_EXIT(3)NAMEpthread_exit - terminate calling threadSYNOPSIS#include <pthread.h>void pthread_exit(void *retval);/*@描述立即结束线程@retval:线程结束之后需要返回的参数,返回值的指针。*/

被别人干掉

  • cancel:被别人取消(其他线程调用pthread_cancel)

    • t1:pthread_cancel(t2)

    • t1调用取消函数,取消t2,t2不一定会被取消

      • 因为t2能不能被其他线程取消,取决于t2线程的一个属性:取消属性

      • 它是否可以被cancelled

 PTHREAD_CANCEL(3)                                  Linux Programmer's Manual     PTHREAD_CANCEL(3)NAMESYNOPSIS#include <pthread.h>int pthread_cancel(pthread_t thread);/*@描述:取消一个指定的线程@thread:线程号,需要取消的那个线程的id号@return:成功返回0,失败返回非0.*/pthread_cancel - send a cancellation request to a thread
SYNOPSIS#include <pthread.h>int pthread_cancel(pthread_t thread);/*@描述:取消一个指定的线程@thread:线程号,需要取消的那个线程的id号@return:成功返回0,失败返回非0.*/
  • 这个属性叫做:可以被取消属性
    • PTHREAD_CANCEL_ENABLE:表示该线程可以被取消
    • PTHREAD_CANCEL_DISABLE:表示该线程不能被取消
 PTHREAD_SETCANCELSTATE(3)                          Linux Programmer's Manual     PTHREAD_SETCANCELSTATE(3)NAMEpthread_setcancelstate, pthread_setcanceltype - set cancelability state 
and typeSYNOPSIS#include <pthread.h>int pthread_setcancelstate(int state, int *oldstate);/*@描述:设置线程取消属性的@state: 设置线程的取消状态PTHREAD_CANCEL_ENABLE:表示该线程可以被取消PTHREAD_CANCEL_DISABLE:表示该线程不能被取消@oldstate:线程上一次的取消状态@return:成功返回0,失败返回其他值*/  

一个线程退出了,并不是所有资源都会释放。一个线程的退出,它资源释放全部被释放,取决于一个属 性

示例

#include <iostream>
#include <pthread.h>
#include <unistd.h>
using namespace std;string str = "你好,线程";
// 线程函数,表示线程启动之后第一时间会执行的函数
void *mythread(void *arg)
{//  存储的是调用前的状态int old_state = 0;// 控制当前线程的可取消性 PTHREAD_CANCEL_DISABLE不能被取消 |PTHREAD_CANCEL_ENABLE可以被取消// pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,& old_state);cout << (old_state == PTHREAD_CANCEL_DISABLE? "不可以被取消":"可以被取消") << endl;while (1){cout  << "子线程:"  << str << endl;sleep(1);}return nullptr;
}int main()
{// 创建线程// 第一次参数,用来存储线程的id号pthread_t tid;pthread_create(&tid, nullptr, mythread, nullptr);// 子线程先指向父线程再打印 保证子线程在父线程后面结束sleep(3);cout << "主线程:" << str << endl;pthread_cancel(tid);sleep(3);return 0;
}

3.3 资源分离

detach:分离属性:

  • ENABLE: 分离资源属性

    • 该线程结束,它的所有资源都会自动释放。
  • DISABLE: 不分离资源

    • 该线程结束,会有部分资源不会自动释放,需要其他线程调用pthread_join这个函数才能完

    全释放

3.3.1 线程资源回收函数
PTHREAD_JOIN(3)                                                   Linux 
Programmer's Manual                                                   
PTHREAD_JOIN(3)NAMEpthread_join - join with a terminated threadSYNOPSIS#include <pthread.h>int pthread_join(pthread_t thread, void **retval);/*@描述:等待一个指定的线程结束 阻塞状态@thread:需要等待的线程id号@retval:二级指针,表示线程函数的返回值指针@return:成功返回0失败返回-1*/
3.3.2 资源分类属性
 PTHREAD_DETACH(3)                                                 Linux 
Programmer's Manual                                                 
PTHREAD_DETACH(3)NAMEpthread_detach - detach a threadSYNOPSIS#include <pthread.h>int pthread_detach(pthread_t thread);/*@描述:设置线程的资源分离属性@thread:需要设置资源分离属性的那个线程id@return:成功返回0失败返回-1*/
3.3.3 获取自身ID号
#include <pthread.h>pthread_t pthread_self(void);/*
作用:
获取当前所在线程的tid号
@return:
返回当前所在线程的tid号
*/

示例

#include <iostream>
#include <pthread.h>
#include <unistd.h>
using namespace std;string str = "你好,线程";
// 线程函数,表示线程启动之后第一时间会执行的函数
void *mythread(void *arg)
{pthread_detach(pthread_self());while (1){cout  << "子线程:"  << str << endl;sleep(1);}return nullptr;
}int main()
{// 创建线程// 第一次参数,用来存储线程的id号pthread_t tid;pthread_create(&tid, nullptr, mythread, nullptr);cout << "主线程:" << str << endl;// 取消线程   pthread_cancel(tid);sleep(3);// 资源回收pthread_join(tid,nullptr);return 0;
}

4. 线程的同步/互斥机制

为了线程之间,能够去有序的访问共享资源,引用信号量机制

  • 信号量System VPOSIX 信号量
  • 线程互斥锁

4.1 线程互斥锁

线程互斥锁也是信号量,只不过线程互斥锁,存在于进程地址空间,用于线程间同步和互斥操作,线程
互斥锁它的效率相对信号量来说要高。
线程互斥锁:使用pthread_mutex_t 的类型来描述一个锁
安装线程POSIX 帮助手册:sudo apt-get install manpages-posix-dev // 安装posix 帮助手册

  • 初始化线程互斥锁
PTHREAD_MUTEX_INIT(3POSIX)                                             POSIX Programmer's 
Manual                             					PTHREAD_MUTEX_INIT(3POSIX)PROLOGThis  manual  page  is part of the POSIX Programmer's Manual.  The Linux 
implementation of this interface may differ (consult thecorresponding Linux manual page for details of Linux behavior), or the 
interface may not be implemented on Linux.NAMEpthread_mutex_init — destroy and initialize a mutexSYNOPSIS#include <pthread.h>int pthread_mutex_init(pthread_mutex_t *restrict mutex,const 
pthread_mutexattr_t *restrict attr);/*@描述:初始一个线程互斥锁@mutex:需要初始化的线程互斥锁地址pthread_mutex_t mutex; // 创建了一个互斥锁	&mutex ---> 互斥锁地址@attr:线程互斥锁的属性,一般为NULL,采用默认属性如:线程的互斥锁默认设置 1 unlock@return:成功返回0,失败返回-1*/
  • 线程互斥锁的PV操作
int pthread_mutex_lock(pthread_mutex_t *mutex);/*作用:死等上锁,如果该锁没有被释放,则会一直阻塞在此函数,等待该锁被释放。@mutex:需要上锁的互斥锁指针@return:成功返回0,表示获取到了该互斥锁返回-1,表示获取出错,没有获取到互斥锁
*/int pthread_mutex_trylock(pthread_mutex_t *mutex);/*作用: 尝试上锁,尝试性上锁,如果该锁没被释放,那么立即返回执行后面的代码。@mutex:需要上锁的互斥锁指针@return:成功返回0,表示获取到了该互斥锁其他值,表示没有获取到互斥锁
*/int pthread_mutex_timedlock(pthread_mutex_t *mutex,struct timespec 
*abs_timeout);
*abs_timeout);/*作用:限时上锁,如果该锁没有被释放,则会一直阻塞在此函数中一段实际,等待该锁被释放。如果时间
过了还没有被释放,那么果断放弃执行后面的代码。@mutex:需要上锁的互斥锁指针@abs_timeout:绝对时间(超时时间),上锁的时间范围。@return:成功返回0,表示获取到了该互斥锁其他值,表示没有获取到互斥锁*/
  • V操作(解锁操作)
int pthread_mutex_unlock(pthread_mutex_t *mutex);/*
作用:
解锁线程互斥锁
@mutex:
需要解锁的线程互斥锁指针
*/
  • 线程互斥锁的销毁操作
int pthread_mutex_destroy(pthread_mutex_t *mutex);/*作用:销毁一个线程互斥锁@mutex:需要销毁的线程互斥锁指针@return:成功返回0,失败返回-1*/

5.生产者消费者模型

生产者消费者模型:利用厂商和消费者关系,由生产者线程进行生产(产生任务),再由消费者线程消 费(执行任务),没有任务的时候,消费者等待生产者产生任务。

  • 共享资源的互斥访问问题
    • 信号量/线程互斥锁

当缓冲区(生产者没有产出的时候)没有数据的时候,(消费者)应该怎么办?

  • 不停的去测试,看有没有数据。

    • 轮询访问,但是轮询有缺陷:一直在访问,浪费CPU资源。轮询有时间差,占用总线:`Is ``

      always busy

  • 让出CPU,当有数据的时候,再唤醒我(wake up),线程条件变量:同步

5.1 线程条件变量

线程条件变量:在多线程程序设计中,可以用条件变量为表示一个特定的条件或者是事件
pthread_cond_t :来描述一个条件变量(类型)
至于条件变量,到底是一个什么事件或者说表示一个什么条件?完全由程序猿去解释这个条件变量所代
表的含义。
在条件变量上的三种操作:

  • 初始化
  • 等待一个条件变量(等待该条件变量所表示的事件)
  • 唤醒一个线程/触发条件变量(唤醒了正在等待该事件的线程)
int data = 0;main : 主线程:生产者:包工头data = 1;t1:子线程:消费者:牛马when data == 1;干活data = 0; 

5.2 线程条件变量 API

5.2.1 初始化/销毁条件变量
PTHREAD_COND_DESTROY(3POSIX)                                      		POSIX 
Programmer's Manual                                      
PTHREAD_COND_DESTROY(3POSIX)PROLOGThis  manual  page  is  part of the POSIX Programmer's Manual.  The Linux 
implementation of this interface may differ (consult the corresponding Linuxmanual page for details of Linux behavior), or the interface may not be 
implemented on Linux.NAMEpthread_cond_destroy, pthread_cond_init — destroy and initialize 
condition variablesSYNOPSIS#include <pthread.h>int pthread_cond_destroy(pthread_cond_t *cond);/*@描述:销毁一个条件变量@cond:需要销毁条件变量指针
*/
  int pthread_cond_init(pthread_cond_t *restrict cond,const 
pthread_condattr_t *restrict attr);/*@描述:初始化一个条件变量@cond:需要初始化的条件变量的指针@attr:初始化的条件变量的属性,一般为NULL,采用默认设置@return:成功返回0,失败返回其他值*/
5.2.2 等待一个条件变量
 PTHREAD_COND_TIMEDWAIT(3POSIX)                                    POSIX 
Programmer's Manual                                    
PTHREAD_COND_TIMEDWAIT(3POSIX)PROLOGThis  manual  page  is  part of the POSIX Programmer's Manual.  The Linux 
implementation of this interface may differ (consult the corresponding Linuxmanual page for details of Linux behavior), or the interface may not be 
implemented on Linux.NAMEpthread_cond_timedwait, pthread_cond_wait — wait on a conditionSYNOPSIS#include <pthread.h>int pthread_cond_timedwait(pthread_cond_t *restrict cond,pthread_mutex_t 
*restrict mutex,const struct timespec *restrict abstime);/*@描述:限时等待条件变量@cond:需要等待的那个条件变量指针@mutex:线程互斥锁:为了保护cond所表示的那个事件/共享资源的。条件变量实际也是一个共享资源。@abstime:绝对时间,需要被唤醒的绝对时间*/int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t 
*restrict mutex);/*@描述:等待那个条件变量@cond:需要等待的那个条件变量指针@mutex:线程互斥锁:为了保护cond所表示的那个事件/共享资源的。条件变量实际也是一个共享资源。@abstime:绝对时间,需要被唤醒的绝对时间*/int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t 
*restrict mutex);/*@描述:等待那个条件变量@cond:需要等待的那个条件变量指针@mutex:线程互斥锁:为了保护cond所表示的那个事件/共享资源的。条件变量实际也是一个共享资源。mutex:locked 上锁pthread_cond_wait(){... 准备工作mutex:unlock 解锁让出CPU 等待...when 当条件产生的时候,其他的线程唤醒我的时候mutex:locked 上锁}@return:成功返回0,被其他线程唤醒失败返回其他值*/
5.3.3 唤醒线程/触发条件变量
PTHREAD_COND_BROADCAST(3POSIX)                                    POSIX 
Programmer's Manual                                    
PTHREAD_COND_BROADCAST(3POSIX)PROLOGThis  manual  page  is  part of the POSIX Programmer's Manual.  The Linux 
implementation of this interface may differ (consult the corresponding Linuxmanual page for details of Linux behavior), or the interface may not be 
implemented on Linux.NAMEpthread_cond_broadcast, pthread_cond_signal — broadcast or signal a 
conditionSYNOPSIS#include <pthread.h>// 广播唤醒int pthread_cond_broadcast(pthread_cond_t *cond);/*@描述:唤醒所有正在等待的线程@cond:那个条件变量@return:成功返回0,失败返回其他值*/// 单个唤醒int pthread_cond_signal(pthread_cond_t *cond);/*@描述:只唤醒一个线程在等待的线程。@cond:那个条件变量@return:成功返回0,失败返回其他值*/

注意:广播唤醒和单个唤醒的区别

  • 广播唤醒:唤醒所有等待的线程,去执行任务,但是任务可能不够分,那么没分到的线程继续休眠
  • 单个唤醒:随机唤醒一个线程执行任务,其他线程继续休眠。
#include <iostream>
#include <vector>
#include <unistd.h>
#include <pthread.h>// 全局变量供父子线程使用
int a = 0;
int b = 0;
// 线程互斥锁
pthread_mutex_t mutex;
// 条件变量
pthread_cond_t cond;
void *myrhtread(void *arg)
{usleep(10);std::cout << "子线程:" << pthread_self() << "启动完成" << std::endl;while (1){// 上锁pthread_mutex_lock(&mutex);// 休息,等待主线程给活,没有就休息等待pthread_cond_wait(&cond, &mutex);//if (a < 0 && b < 0){//小于0时候退先解锁在退出pthread_mutex_unlock(&mutex);break;}std::cout << "子线程:" << pthread_self()  << "计算结果是:" << a + b << std::endl;// 解锁pthread_mutex_unlock(&mutex);}return nullptr;
}
int main()
{// 初始化互斥锁pthread_mutex_init(&mutex, nullptr);// 初始化条件变量pthread_cond_init(&cond, nullptr);// 定义五个工作者(牛马)std::vector<pthread_t> works;// 创建线程for (int i = 0; i < 5; i++){pthread_t tid;pthread_create(&tid, nullptr, myrhtread, nullptr);// 添加到容器里面works.push_back(tid);}usleep(10);// 生产者while (1){// 上锁pthread_mutex_lock(&mutex);std::cout << "请输入" << std::endl;std::cin >> a >> b;// 退出条件if(a < 0 && b < 0){pthread_mutex_unlock(&mutex);break;}// 解锁pthread_mutex_unlock(&mutex);// 唤醒线程可以工作了pthread_cond_signal(&cond);usleep(10);}// 唤醒全部线程逐步退出pthread_cond_broadcast(&cond);// 等待工作者线程结束for(pthread_t tid:works){pthread_join(tid, nullptr);}// 销毁条件变量pthread_cond_destroy(&cond);// 销毁锁pthread_mutex_destroy(&mutex);
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/bicheng/83415.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AAAI 2025论文分享│STD-PLM:基于预训练语言模型的时空数据预测与补全方法

本文详细介绍了一篇发表于人工智能顶级会议AAAI 2025的论文《STD-PLM: Understanding Both Spatial and Temporal Properties of Spatial-Temporal Data with PLM》。该论文提出了一种基于预训练语言模型&#xff08;Pre-trained Language Model‌&#xff0c;PLM&#xff09;的…

前端八股 tcp 和 udp

都是传输层协议 udp 数据报协议 不可靠面向数据包对于应用层传递的报文加上UDP首部就传给网络层 tcp 传输控制协议 可靠 会将报文分段进行传输 区别&#xff1a; 1.tcp 可靠 udp 不可靠 2.tcp 面向连接 三握四挥 udp 无连接 3.tcp面向字节流 udp面向报文 4.效率低 效率高…

MES管理系统:Java+Vue,含源码与文档,实现生产过程实时监控、调度与优化,提升制造企业效能

前言&#xff1a; 在当今竞争激烈的制造业环境中&#xff0c;企业面临着提高生产效率、降低成本、提升产品质量以及快速响应市场变化等多重挑战。MES管理系统作为连接企业上层计划管理系统与底层工业控制之间的桥梁&#xff0c;扮演着至关重要的角色。它能够实时收集、分析和处…

MSTNet:用于糖尿病视网膜病变分类的多尺度空间感知 Transformer 与多实例学习方法|文献速递-深度学习医疗AI最新文献

Title 题目 MSTNet: Multi-scale spatial-aware transformer with multi-instance learning for diabetic retinopathy classification MSTNet&#xff1a;用于糖尿病视网膜病变分类的多尺度空间感知 Transformer 与多实例学习方法 01 文献速递介绍 糖尿病视网膜病变&#…

每日八股文6.2

每日八股-6.2 Go1.GMP调度原理&#xff08;这部分多去看看golang三关加深理解&#xff09;2.GC&#xff08;同样多去看看golang三关加深理解&#xff09;3.闭包4.go语言函数是一等公民是什么意思5.sync.Mutex和sync.RWMutex6.sync.WaitGroup7.sync.Cond8.sync.Pool9.panic和rec…

【Unity】相机 Cameras

1 前言 主要介绍官方文档中相机模块的内容。 关于“9动态分辨率”&#xff0c;这部分很多API文档只是提了一下&#xff0c;具体细节还需要自己深入API才行。 2 摄像机介绍 Unity 场景在三维空间中表示游戏对象。由于观察者的屏幕是二维屏幕&#xff0c;Unity 需要捕捉视图并将…

SpringBoot(六)--- AOP、ThreadLocal

目录 前言 一、AOP基础 1.入门程序 2. AOP核心概念 3. 底层原理 二、AOP进阶 1.通知类型 抽取切入点 2. 切入点表达式 2.1 execution 2.2 annoation 2.3 连接点详解 三、ThreadLocal 前言 AOP&#xff08;面向切面编程&#xff09;&#xff0c;面向切面编程实际就…

【深度学习】 19. 生成模型:Diffusion Models

Diffusion Models Diffusion Models 简介 Diffusion 模型是一类通过逐步添加噪声并再逆向还原的方式进行图像生成的深度生成模型。其基本流程包括&#xff1a; 前向过程&#xff08;Forward Process&#xff09;&#xff1a;将真实图像逐步加噪&#xff0c;最终变为高斯噪声…

Y1——链式前向星

知识点 模版——链表的前插法 head表示头结点的下标 ver[i]表示结点i 的值 tot存储当前已经用到了哪个 add用于将x插到头结点 int head1; intt ver[N],Next[N]; int ttot-1; void add(int x){ver[tot]x;Next[tot]head;headtot; } 常见的链式前向星三种实现形式&#xff…

如何排查Redis单个Key命中率骤降?

问题现象 Redis整体命中率98%&#xff0c;但监控发现特定Key&#xff08;如user:1000:profile&#xff09;的命中率从99%骤降至40%&#xff0c;引发服务延迟上升。 排查步骤 1. 确认现象与定位Key // 通过Redis监控工具获取Key指标 public void monitorKey(String key) {Je…

自定义Shell命令行解释器

目录 1、目标 2、显示命令提示符 2.1 getenv 2.2 getcwd 2.3 putenv 3、获取用户输入的命令 4、解析命令 5、处理内建命令 6、处理外部命令 7、完整代码 7.1 myshell.cpp 7.2 Makefile 1、目标 实现一个Linux的myshell&#xff0c;有以下基本的功能。 显示命令提示…

Laplace 噪声

Laplace 噪声是一种特定概率分布&#xff08;拉普拉斯分布&#xff09;产生的随机扰动。它是差分隐私&#xff08;Differential Privacy, DP&#xff09;中最核心、最常用的噪声机制之一。它的核心作用是在不泄露个体信息的前提下&#xff0c;允许从包含敏感数据的数据库中提取…

基于空天地一体化网络的通信系统matlab性能分析

目录 1.引言 2.算法仿真效果演示 3.数据集格式或算法参数简介 4.MATLAB核心程序 5.算法涉及理论知识概要 5.1 QPSK调制原理 5.2 空天地一体化网络信道模型 5.3 空天地一体化网络信道特性 6.参考文献 7.完整算法代码文件获得 1.引言 空天地一体化网络是一种将卫星通信…

【Delphi】接收windows文件夹中文件拖拽

本文根据EmailX45的视频文件&#xff0c;进行了优化改进&#xff0c;原文参见&#xff1a;Delphi: Drag and Drop Files from Explorer into TPanel / TMemo - YouTube 在Windows中&#xff0c;如果将选择的文件拖动到Delphi程序的控件上&#xff0c;有很多实现方法&#xff0c…

基于热力学熵增原理的EM-GAN

简介 简介:提出基于热力学熵增原理的EM-GAN,通过生成器熵最大化约束增强输出多样性。引入熵敏感激活函数与特征空间熵计算模块,在MNIST/CelebA等数据集上实现FID分数提升23.6%,有效缓解模式崩溃问题。 论文题目:Entropy-Maximized Generative Adversarial Network (EM-G…

HashMap与ConcurrentHashMap详解:实现原理、源码分析与最佳实践

引言 在Java编程中&#xff0c;集合框架是最常用的工具之一&#xff0c;而HashMap和ConcurrentHashMap则是其中使用频率最高的两个Map实现。它们都用于存储键值对数据&#xff0c;但在实现机制、性能特点和适用场景上有着显著差异。 HashMap作为单线程环境下的首选Map实现&am…

CSS之动画(奔跑的熊、两面反转盒子、3D导航栏、旋转木马)

一、 2D转换 1.1 transform: translate( ) 转换&#xff08;transform&#xff09; 是CSS3中具有颠覆性的特征之一&#xff0c;可以实现元素的位移、旋转、缩放等效果 移动&#xff1a;translate 旋转&#xff1a;rotate 缩放&#xff1a;scale 下图为2D转换的坐标系 回忆…

【笔记】在 MSYS2(MINGW64)中安装 python-maturin 的记录

#工作记录 &#x1f4cc; 安装背景 操作系统&#xff1a;MSYS2 MINGW64当前时间&#xff1a;2025年6月1日Python 版本&#xff1a;3.12&#xff08;通过 pacman 安装&#xff09;目标工具&#xff1a;maturin —— 用于构建和发布 Rust 编写的 Python 包 &#x1f6e0;️ 安装…

基于微信小程序的垃圾分类系统

博主介绍&#xff1a;java高级开发&#xff0c;从事互联网行业六年&#xff0c;熟悉各种主流语言&#xff0c;精通java、python、php、爬虫、web开发&#xff0c;已经做了六年的毕业设计程序开发&#xff0c;开发过上千套毕业设计程序&#xff0c;没有什么华丽的语言&#xff0…

工作日记之权限校验-token的实战案例

背景说明 我们组负责维护的一个系统&#xff0c;前端界面挂载在其他两个系统上&#xff0c;因为历史遗留原因&#xff0c;同时也挂在公网上&#xff0c;没有登陆功能和用户体系&#xff0c;只要输入网址就能访问&#xff0c;虽然这个系统是给公司内部人员使用&#xff0c;但是…