僵尸进程的避免 守护进程的创建 线程的创建,阻塞,数据传递 5.15

news2024/11/26 2:52:26

父子进程相关知识:

1.子进程结束时,系统 会立即自动刷新行缓存

2.手动结束进程:

exit()

exit(int status):结束当前调用的进程,自动刷新缓存

标准库函数

头文件:#include <stdlib.h>

_exit()

_exit(int status) : 结束当前调用的进程,不刷新缓存

系统调用函数

头文件:#include <unistd.h>

3.僵尸进程

子进程先于父进程结束,父进程没有回收子进程的剩余资源

4.如何避免僵尸进程?

1、子进程结束,通知父进程回收资源,使用wait或者waitpid函数

wait()

​ pid_t wait(int *status)

功能:阻塞父进程,等待任一子进程结束,回收该子进程资源

在父进程中调用

如果,该进程没有子进程或者子进程已经结束,则函数立即返回

头文件:

​ #include <sys/types.h>

​ #include <sys/wait.h>

参数:

​ status : 整型指针,用来保存子进程退出时的状态

​ 如果status设置为NULL,不保存子进程退出时的状态

​ 必须通过Linux的宏来检测 退出状态

返回值:

​ 成功:退出的子进程的pid

​ 失败:-1,并设置错误信息

5.fork创建子进程时:

if结构 将会决定 子进程拷贝父进程的 哪些内容:

if()

{//出错}

else if()

{//子进程}

else

{//父进程}

注意:else中的父进程区域内容不会被拷贝到子进程中

if()

{//出错}

else if()

{//子进程}

//父进程区域(没有else)

注意:父进程的内容,将会被子进程 拷贝所有内容(父进程号除外)

waitpid()

​ pid_t waitpid(pid_t pid,int *status,int options)

waitpid(-1,NULL,0) == wait(NULL)

功能:

​ 回收指定 pid的子进程 资源

参数:

​ pid:要回收的子进程的pid号;

​ status:保存指定pid的子进程退出的状态

​ option:WNOHANG:非阻塞模式;子进程未结束,立即返回0值;当指定的子进程PID结束立即回收资源

​ 0:阻塞模式,等同于wait

返回值:

​ 成功:返回退出的子进程PID号;

​ 失败:返回-1;

5.孤儿进程

父进程先于子进程结束,子进程被init.d托管,init进程的PID号为1

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UyM3kYL1-1684249118083)(C:\Users\孤独memories\AppData\Roaming\Typora\typora-user-images\image-20230515133844707.png)]

缺点:

​ 孤儿进程无法受当前终端控制。除非使用kill命令杀死或者系统结束,否则一直存在。

应用:用来制作守护进程

6.创建守护进程

ps -ef 全部进程

ps -axj 查看守护进程

ps -aux 全部进程

1、先创建子进程,父进程结束,形成孤儿进程

2、创建新的会话期,使进程完全独立,摆脱当前进程的控制

setsid函数用于创建一个新的会话期,kill -9杀不死

3、改变进程的工作目录为根目录:chdir

“/”或者“/tmp”作为守护

4、重设文件权限掩码:umask(0)

目的:增加守护进程的灵活性

5、关闭其他不相关的文件描述符。

运行之后,可以用kill -9 强制杀死守护进程,因为kill -9是在内核层面上杀死,而守护进程开辟是在用户层面的进程可以被其他杀死。

hqyj@ubuntu:~/5.15$ cat guer1_demo.c 
/*===============================================
*   文件名称:fork_demo.c
*   创 建 者:memories 
*   创建日期:2023年05月15日
*   描    述:
================================================*/
    
    创建守护进程
    
    
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <string.h>
#include <fcntl.h>

void process();

int main(int argc, char *argv[])
{ 
    pid_t pid=fork();
    if(pid==-1)
    {
        perror("fork");
        return -1;
    }
    else if(pid==0)
    {
        //2.创建新的会话期
        if(setsid()<0)
        {
            perror("setsid");
            return -1;
        }
        //3.设置进程的工作目录为"/tmp"
        if(chdir("../5.15")<0)
        {
            perror("chidr");
            return -1;
        }
        //4.重设文件权限掩码
        umask(0);

        //5.关闭不相关的文件描述符(文件描述符来自于父进程)
        //getdtablesize():返回当前的文件描述符个数
        for(int i=0;i<getdtablesize();i++)
        {
            close(i);
        }
        //调用接口函数,实现记录功能,每隔一秒钟向文件下入记数
        process();
    }
    else
    {
        //1.父进程推出 孤儿进程创建
        exit(0);
    }
    return 0;
} 


void process()
{
    int fd = open("file1.txt",O_RDWR|O_CREAT,0640);
    int count = 0;

    while(1)
    {
        char buf[5]={0};
        sprintf(buf,"%d ",count++);
        write(fd,buf,strlen(buf));
        sleep(1);
    }

}
hqyj@ubuntu:~/5.15$ cat file1.txt
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 
hqyj@ubuntu:~/5.15$ cat file1.txt 
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 

线程

  1. 每个进程的地址空间都是私有的,都拥有自己的task_struct结构体,每个task_struct都会指向自己映射的memory map虚拟地址映射表

  2. 当进程间进行任务切换时,都需要访问不同的task_struct结构体,因此需要不断刷新cache高速缓存器和TLB页表,导致系统开销大。因此,引入线程的概念,减小任务切换时系统开销较大的问题,提升系统性能

  3. 线程是轻量级的进程。

    同一个进程中开启的多个线程,共享同一个进程地址空间

    多个线程共同使用一个task_struct结构体

  4. 使用线程的好处

								1、提高了线程间任务切换的效率

								2、避免了额外的TLB和cache缓存的刷新
  1. posix线程库操作函数接口:

pthread

1、int pthread_create(pthread_t *tid,const pthread_attr_t *attr,void *( *routine)(void *),void *arg);

功能:

创建新的子线程,指定线程的属性,指定线程的执行函数

头文件:

​ #include <pthread.h>

参数:

​ tid:保存创建成功的线程ID号

​ attr:指定线程的属性,默认为NULL缺省属性

​ routine:指针函数指针,指向线程的执行函数(void *函数名(void *);指针函数)

​ arg:传递到线程执行函数的参数

返回值:

​ 成功:0

​ 失败:posix库中的错误码

***注意:程序编译时必须指定链接的动态库 -lpthread

gcc *.c -lpthread;

/*===============================================
*   文件名称:pthread_demo.c
*   创 建 者:memories 
*   创建日期:2023年05月15日
*   描    述:
================================================*/

创建线程12,打印相应的内容
并不关闭线程


#include <stdio.h>
#include <unistd.h>
#include <pthread.h> //第三方线程库的头文件

void *thread1(void *arg)//定义一个指针函数,用作一个线程的执行函数
{
    //线程的代码区域
    while(1)//阻止子线程的结束
    {
        printf("child thread1\n");
        sleep(1);
    }
}
void *thread2(void *arg)//定义一个指针函数,用作一个线程的执行函数
{
    //线程的代码区域
    while(1)//阻止子线程的结束
    {
        printf("child thread2\n");
        sleep(1);
    }
}
int main(int argc, char *argv[])
{ 
    //创建线程:pthread_create(pthread_t *tid,const pthread_attr_t *attr,void *(* routine)(void *),void *arg);
    pthread_t tid;
    if(pthread_create(&tid,NULL,thread1,NULL) <0 )
    {
        printf("create thread1 filed\n");
        return -1;
    }
    if(pthread_create(&tid,NULL,thread2,NULL) <0 )
    {
        printf("create thread2 filed\n");
        return -1;
    }
    while(1)
    {
        printf("main process\n");
        sleep(1);
    }
        return 0;
} 

hqyj@ubuntu:~/5.15$ gcc pthread_demo.c -lpthread
hqyj@ubuntu:~/5.15$ ./a.out 
main process
child thread1
child thread2
main process
child thread1
child thread2
main process
child thread1
child thread2
main process
child thread1
child thread2
^C

pthread_exit(void *str);

2、void pthread_exit(void *str);

功能:

​ 手动退出当前线程,传递数据。

参数:

​ str:要传递的数据的首地址

返回值:

​ 无

/*===============================================
*   文件名称:pthread_demo.c
*   创 建 者:memories 
*   创建日期:2023年05月15日
*   描    述:
================================================*/

1.创建子线程12
2.阻塞等待,指定的子线程12退出,回收资源子线程中的资源,
    其中的资源thread 1 exit,thread 2 exit


#include <stdio.h>
#include <unistd.h>
#include <pthread.h> //第三方线程库的头文件

void *thread1(void *arg)//定义一个指针函数,用作一个线程的执行函数
{
    //线程的代码区域
        printf("child thread1\n");
        sleep(2);
        pthread_exit("thread 1 exit");
}
void *thread2(void *arg)//定义一个指针函数,用作一个线程的执行函数
{
    //线程的代码区域
        printf("child thread2\n");
        sleep(5);
        pthread_exit("thread 2 exit");
}
int main(int argc, char *argv[])
{ 
    //创建线程:pthread_create(pthread_t *tid,const pthread_attr_t *attr,void *(* routine)(void *),void *arg);
    pthread_t tid,tid2;
    if(pthread_create(&tid,NULL,thread1,NULL) <0 )
    {
        printf("create thread1 filed\n");
        return -1;
    }
    if(pthread_create(&tid2,NULL,thread2,NULL) <0 )
    {
        printf("create thread2 filed\n");
        return -1;
    }

    char *res;
        pthread_join(tid,(void **)&res);//阻塞等待,指定的子线程退出,回收资源
        printf("main process=%s\n",res);
        pthread_join(tid2,(void **)&res);
        printf("main process=%s\n",res);
        while(1);

        return 0;
} 

hqyj@ubuntu:~/5.15$ gcc pthread_exit.c -lpthread 
hqyj@ubuntu:~/5.15$ ./a.out 
child thread2
child thread1
main process=thread 1 exit
main process=thread 2 exit
^c

/*===============================================
*   文件名称:pthread_demo.c
*   创 建 者:memories 
*   创建日期:2023年05月15日
*   描    述:
================================================*/


1.创建子线程12
2.阻塞等待,指定的子线程12退出,回收资源子线程中的资源,
    其中的资源thread 1 exit,thread 2 exit

#include <stdio.h>
#include <unistd.h>
#include <pthread.h> //第三方线程库的头文件

void *thread1(void *arg)//定义一个指针函数,用作一个线程的执行函数
{
    //线程的代码区域
        printf("child thread1\n");
        sleep(2);
        pthread_exit("thread 1 exit");
}
void *thread2(void *arg)//定义一个指针函数,用作一个线程的执行函数
{
    //线程的代码区域
        printf("child thread2\n");
        sleep(5);
        pthread_exit("thread 2 exit");
}
int main(int argc, char *argv[])
{ 
    //创建线程:pthread_create(pthread_t *tid,const pthread_attr_t *attr,void *(* routine)(void *),void *arg);
    pthread_t tid,tid2;
    if(pthread_create(&tid,NULL,thread1,NULL) <0 )
    {
        printf("create thread1 filed\n");
        return -1;
    }
    if(pthread_create(&tid2,NULL,thread2,NULL) <0 )
    {
        printf("create thread2 filed\n");
        return -1;
    }
        pthread_detach(tid);//非阻塞等待
        pthread_detach(tid2);
        printf("main-------\n");
        while(1);
        return 0;
} 

qyj@ubuntu:~/5.15$ gcc pthread_exit.c -lpthread 
hqyj@ubuntu:~/5.15$ ./a.out 
main-------
child thread2
child thread1
^c

pthread_join(pthread_t tid,void **str);

3、 int pthread_join(pthread_t tid,void **str);

功能:阻塞主进程,等待指定线程的退出,回收资源,并保存子线程退出时传递的数据

参数:

​ tid:线程ID

​ str:二级指针,用来保存线程退出时传递的数据

返回值:

​ 成功:0

​ 失败:线程库的错误码

/*===============================================
 *   文件名称:pthread_demo.c
 *   创 建 者:memories 
 *   创建日期:2023年05月15日
 *   描    述:
 ================================================*/

1.创建线程12
2.等待线程1关闭之后打印pthread1 quit
3.等待线程2关闭之后打印main process

#include <stdio.h>
#include <unistd.h>
#include <pthread.h> //第三方线程库的头文件

void *thread1(void *arg)//定义一个指针函数,用作一个线程的执行函数
{
    //线程1的代码区域
    printf("child thread1\n");
    sleep(3);
}
void *thread2(void *arg)//定义一个指针函数,用作一个线程的执行函数
{
    //线程2的代码区域
    printf("child thread2\n");
    sleep(5);
}
int main(int argc, char *argv[])
{ 
    //创建线程:pthread_create(pthread_t *tid,const pthread_attr_t *attr,void *(* routine)(void *),void *arg);
    pthread_t tid,tid2;
    if(pthread_create(&tid,NULL,thread1,NULL) <0 )
    {
        printf("create thread1 filed\n");
        return -1;
    }
    if(pthread_create(&tid2,NULL,thread2,NULL) <0 )
    {
        printf("create thread2 filed\n");
        return -1;
    }
    pthread_join(tid,NULL);//阻塞等待 指定的子线程退出 回收资源
    printf("thread1 quit\n");
    pthread_join(tid2,NULL);
    printf("main process\n");
    return 0;
} 

hqyj@ubuntu:~/5.15$ gcc pthread1_demo.c -lpthread
hqyj@ubuntu:~/5.15$ ./a.out 
child thread1
child thread2
thread1 quit
main process

同一进程中的多个线程之间进行数据传递必须使用全局变量。

/*===============================================
*   文件名称:pthread_demo.c
*   创 建 者:memories 
*   创建日期:2023年05月15日
*   描    述:
================================================*/

1.定义一个全局变量a,将a在两个线程之间进行数据传递
2.也可以在进程中定义一个变量b,但只能以函数传递参数的方式,使得b在两个线程之间进行数据传递


#include <stdio.h>
#include <unistd.h>
#include <pthread.h> //第三方线程库的头文件

int a=10;

void *thread1(void *arg)//定义一个指针函数,用作一个线程的执行函数
{
    //int b=*(int *)arg;
    //线程的代码区域
    while(1)
    {
        printf("child thread1=%d,b=%d\n",a++,(*(int *)arg)++);
        sleep(1);
    }
}
void *thread2(void *arg)//定义一个指针函数,用作一个线程的执行函数
{
    //int b=*(int *)arg;
    //线程的代码区域
    while(1)
    {
        printf("child thread2=%d,b=%d\n",a,*(int *)arg);
        sleep(1);
    }
}
int main(int argc, char *argv[])
{ 
    int b=10;
    //创建线程:pthread_create(pthread_t *tid,const pthread_attr_t *attr,void *(* routine)(void *),void *arg);
    pthread_t tid,tid2;
    if(pthread_create(&tid,NULL,thread1,(void *)&b) <0 )
    {
        printf("create thread1 filed\n");
        return -1;
    }
    if(pthread_create(&tid2,NULL,thread2,(void *)&b) <0 )
    {
        printf("create thread2 filed\n");
        return -1;
    }
    while(1);
        return 0;
} 

hqyj@ubuntu:~/5.15$ gcc pthread_data.c -lpthread
hqyj@ubuntu:~/5.15$ ./a.out 
child thread1=10,b=10
child thread2=11,b=11
child thread1=11,b=11
child thread2=12,b=12
child thread1=12,b=12
child thread2=13,b=13
child thread1=13,b=13
child thread2=14,b=14
child thread1=14,b=14
child thread2=15,b=15
^C

/*===============================================
*   文件名称:pthread_demo.c
*   创 建 者:memories 
*   创建日期:2023年05月15日
*   描    述:
================================================*/

a为全局变量则可以使得a现在线程12之间进行数据传递
    
但b这种不同于上种类型  当int b=*(int *)arg; 在线程2定义过一次之后,此时b在线程2为局部变量,无法进行线程间的数据传递


#include <stdio.h>
#include <unistd.h>
#include <pthread.h> //第三方线程库的头文件

int a=10;

void *thread1(void *arg)//定义一个指针函数,用作一个线程的执行函数
{
    //int b=*(int *)arg;
    //线程的代码区域
    while(1)
    {
        printf("child thread1=%d,b=%d\n",a++,(*(int *)arg)++);
        sleep(1);
    }
}
void *thread2(void *arg)//定义一个指针函数,用作一个线程的执行函数
{
    int b=*(int *)arg;
    //线程的代码区域
    while(1)
    {
        printf("child thread2=%d,b=%d\n",a,b);
        sleep(1);
    }
}
int main(int argc, char *argv[])
{ 
    int b=10;
    //创建线程:pthread_create(pthread_t *tid,const pthread_attr_t *attr,void *(* routine)(void *),void *arg);
    pthread_t tid,tid2;
    if(pthread_create(&tid,NULL,thread1,(void *)&b) <0 )
    {
        printf("create thread1 filed\n");
        return -1;
    }
    if(pthread_create(&tid2,NULL,thread2,(void *)&b) <0 )
    {
        printf("create thread2 filed\n");
        return -1;
    }
    while(1);
        return 0;
} 



hqyj@ubuntu:~/5.15$ gcc pthread_data.c -lpthread
hqyj@ubuntu:~/5.15$ ./a.out 
child thread1=10,b=10
child thread2=11,b=11
child thread1=11,b=11
child thread2=12,b=11
child thread1=12,b=12
child thread2=13,b=11
child thread1=13,b=13
child thread2=14,b=11
child thread1=14,b=14
child thread2=15,b=11
child thread1=15,b=15
child thread2=16,b=11
child thread1=16,b=16
child thread2=17,b=11
^C

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

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

相关文章

压缩技术与常见linux解压/压缩命令总结

文章目录 1 RAR1.1 参数介绍1.2 压缩/解压1.3 分卷压缩/解压 2 7-Zip2.1 常用参数2.2 使用2.3 分卷压缩/解压 3 解压/压缩命令 总结 1 RAR RAR是一种专利文件格式&#xff0c;用于数据的压缩打包。 提供了强力压缩、分卷、加密和自解压模块 官方网址&#xff1a;https://www…

公有云——阿里云ECS服务器(IaaS)

作者简介&#xff1a;一名云计算网络运维人员、每天分享网络与运维的技术与干货。 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a;网络豆的主页​​​​​​ 目录 前言 一.了解云服务器的基础概念 1.云服务器的基础概念&#xff08;云服务器选择…

用IDEA写的第一个JavaWeb项目(保姆级)

任何事情只有0次和无数次&#xff0c;项目新建了第一个就有第二个 从第一次的略显青涩到后面的轻车熟路&#xff0c;区别就是第一次 ——Lungcen 在IDEA中新建一个web项目&#xff0c;有好几种方法。本人用的方法是通过maven构建工具来构建java项目的框架。对于web服务器的选择…

日志—加索引优化select

今天工作中遇到一个小问题&#xff0c;一个搜索接口&#xff0c;要加一个2个字段用于搜索 分析&#xff1a;这两个字段要在子表中去查询&#xff0c;查看原来mapper中的接口&#xff0c;已经连了N个子表&#xff0c;sql速度在10秒左右。 加上了新的子表&#xff0c;然后去试了…

悼念浩哥(左耳朵耗子),一个纯粹的技术人

上周末听闻浩哥的事了&#xff0c;期初还不信。在网上搜索消息&#xff0c;看来是真的。他才四十多岁&#xff0c;觉得非常可惜。很早就关注过浩哥&#xff0c;他是一位正直纯粹和爱分享的技术大牛。无论是技术分享还是人生感悟&#xff0c;或者是成长相关&#xff0c;都让我学…

展会直击 | 昂视精彩亮相CIBF2023深圳国际电池展

5月16日&#xff0c;CIBF2023深圳国际电池展在深圳国际会展中心&#xff08;宝安新馆&#xff09;正式开幕&#xff0c;昂视携2D视觉产品、3D视觉产品、锂电行业智能检测方案亮相9号馆T101-2展位&#xff0c;会场氛围火热&#xff0c;昂视展位人声鼎沸。 方案演示&#xff0c;助…

K8s进阶1——搭建K8s高可用集群

文章目录 一、资源清单二、系统初始化2.1 所有服务器配置2.2 master节点配置 三、nginxkeepalived3.1 主备机器上进行3.2 配置主节点3.3 配置备节点3.4 启动服务 四、部署etcd集群4.1 资源清单4.2 生成Etcd证书4.3 部署Etcd集群 五、安装Docker/kubeadm/kubelet5.1 安装docker5…

【数据库复习】第六章 关系数据理论 1

关系模式的设计 按照一定的原则从数量众多而又相互关联的数据中&#xff0c;构造出一组既能较好地反映现实世界&#xff0c;而又有良好的操作性能的关系模式 ●冗余度高 ●修改困难 ●插入问题 ●删除问题 ★产生问题的原因 属性间约束关系&#xff08;即数据间的依赖关系…

【C++从0到王者】第五站:类和对象(中)const和取地址运算符重载

文章目录 一、const修饰this指针二、取地址运算符重载以及const取地址运算符重载 一、const修饰this指针 我们继续使用之前实现的日期类&#xff0c;当我们写出如下代码的时候&#xff0c;我们可以观察到编译器报错了 这其实因为权限的放大&#xff0c;如下图所示&#xff0c;…

ML之VAR:基于上海最高气温数据集利用时间序列模型之VAR向量自回归模型/多变量自回归模型实现回归预测案例

ML之VAR&#xff1a;基于上海最高气温数据集利用时间序列模型之VAR向量自回归模型/多变量自回归模型实现回归预测案例 目录 基于上海最高气温数据集利用时间序列模型之VAR向量自回归模型/多变量自回归模型实现回归预测案例 # 1、定义数据集 # 2、数据集预处理 # 2.1、缺失值…

【Spring全家桶系列】Spring中的事务管理(基于注解完成实现)

⭐️前面的话⭐️ 本文已经收录到《Spring框架全家桶系列》专栏&#xff0c;本文将介绍Spring中的事务管理&#xff0c;事务的概念与作用&#xff0c;以及Spring事务的属性和传播机制。 &#x1f4d2;博客主页&#xff1a;未见花闻的博客主页 &#x1f389;欢迎关注&#x1f5…

怀念浩哥(左耳朵耗子),一个纯粹的技术人

上周末听闻浩哥的事了&#xff0c;期初还不信。在网上搜索消息&#xff0c;看来是真的。他才四十多岁&#xff0c;觉得非常可惜。很早就关注过浩哥&#xff0c;他是一位正直纯粹和爱分享的技术大牛。无论是技术分享还是人生感悟&#xff0c;或者是成长相关&#xff0c;都让我学…

Portainer: 带你领略强大且易用的容器管理平台

什么是Portainer? Portainer是一个强大的容器管理平台 Portainer是一款轻量级的应用,它提供了图形化界面,用于方便地管理Docker环境,包括单机环境和集群环境。Portainer全球最受欢迎的容器管理平台,拥有超过100万用户和24,600颗GitHub星Portainer的定位及与周边生态的交互…

【Redis】聊一下持久化机制-AOF

前言 持久化其实在任何存储系统中&#xff0c;都是避不开的话题&#xff0c;比如数据库系统就有ACID进行数据、日志的持久化。将文件写入到内存、缓存、磁盘中。在比如消息队列Kafka也有消息的持久化机制&#xff0c;为防止数据的丢失也需要将数据持久化存储。目的其实就是为了…

javaweb系列- JavaScript事件

1.6 JavaScript事件 1.6.1 事件介绍 如下图所示的百度注册页面&#xff0c;当我们用户输入完内容&#xff0c;百度可以自动的提示我们用户名已经存在还是可以使用。那么百度是怎么知道我们用户名输入完了呢&#xff1f;这就需要用到JavaScript中的事件了。 什么是事件呢&…

【SpringBoot】整合第三方技术Junit. MybatisPlus druid

【SpringBoot】整合第三方技术 整合junit整合MyBatis整合Mybatis-plus使用阿里云创建工程 SpringBoot整合druid 整合junit 自己定义一个功能&#xff0c;测试功能接口 测试步骤注入你要测试的对象 提前声明为bean资源执行你要测试的方法 package com.ustc.sp7;import com.us…

MySQL—MVCC

文章目录 数据库并发的场景有三种MVCC概念读-写3个记录隐藏列字段undo log模拟MVCC Read ViewRC与RR的本质区别RCRR 数据库并发的场景有三种 读-读: 不存在任何问题&#xff0c;也不需要并发控制 读-写∶有线程安全问题&#xff0c;可能会造成事务隔离性问题&#xff0c;可能遇…

阿里云GPU服务器租用费用包年包月、一个小时和学生价格

阿里云GPU服务器租用价格表包括包年包月、一个小时收费以及学生GPU服务器租用费用&#xff0c;阿里云GPU计算卡包括NVIDIA V100计算卡、T4计算卡、A10计算卡和A100计算卡&#xff0c;GPU云服务器gn6i可享受3折&#xff0c;阿里云百科分享阿里云GPU服务器租用价格表、GPU一个小时…

chatgpt赋能Python-aidlearning安装python

安装Python的必要性和意义 Python是一种非常流行的编程语言&#xff0c;它的易学易用&#xff0c;高效实用&#xff0c;使得很多人选择使用Python进行编程。对于AI学习&#xff0c;Python更是至关重要&#xff0c;因为很多AI框架和算法都需要使用Python进行编写和实现。因此&a…

Java设计模式 14-访问者模式

访问者模式 这个模式用的很少&#xff0c;《设计模式》的作者评价为&#xff1a; 大多情况下&#xff0c;你不需要使用访问者模式&#xff0c;但是一旦需要使用它时&#xff0c;那就真的需要使用了 一、测评系统的需求 1)将观众分为男人和女人&#xff0c;对歌手进行测评&…