IO进程线程的通信操作

news2024/11/24 9:39:08

1.编程实现互斥机制

程序代码:

  1 #include<myhead.h>
  2 int num=520;//临界资源
  3 //1.创建一个互斥锁变量
  4 pthread_mutex_t mutex;//定义一个pthread_mutex_t类型的变量
  5 //定义任务1函数
  6 void *task1(void *arg)
  7 {
  8     printf("不畏过去\n");
  9     //获取锁资源
 10     pthread_mutex_lock(&mutex);//互斥锁地址
 11     num=1314;
 12     sleep(3);
 13     printf("task1:num=%d\n",num);
 14     //释放锁资源
 15     pthread_mutex_unlock(&mutex);//互斥锁地址
 16 }
 17 //定义任务2函数
 18 void *task2(void *arg)
 19 {
 20     printf("不惧将来\n");
 21     //获取锁资源
 22     pthread_mutex_lock(&mutex);
 23     num++;   //521
 24     sleep(1);  //休眠,执行任务一的赋值语句num=1314
 25     //遇到任务1中的互斥锁,回到这等休眠结束,执行任务二所有程序
 26     printf("task2:num=%d\n",num);
 27     //释放锁资源
 28     pthread_mutex_unlock(&mutex);
 29     //释放完再回到任务一的互斥锁位置,执行任务一所以程序
 30 }
 31 int main(int argc, const char *argv[])
 32 {
 33     //2.初始化互斥锁
 34     pthread_mutex_init(&mutex,NULL);//互斥锁地址,互斥锁属性,成败返回0
 35     //创建两个线程
 36     pthread_t tid1,tid2;//线程号变量
 37     if(pthread_create(&tid1,NULL,task1,NULL)!=0)
 38     //创建分支线程,成0败错误码(不是置位错误码)
 39    //线程号指针,线程属性,线程体(函数指针),线程体的参数
 40     {
 41         printf("tid1 create error\n");//是POSIX库错误码,不能用ferror()
 42         return 0;
 43     }
 44     if(pthread_create(&tid2,NULL,task2,NULL)!=0)
 45     {
 46         printf("tid2 create error\n");
 47         return 0;
 48     }
 49     printf("tid1:%#lx,tid2:%#lx\n",tid1,tid2);//线程号
 50     //回收线程资源
 51     pthread_join(tid1,NULL);//阻塞等待指定线程的退出,收尸,成0败错误码
 52     pthread_join(tid2,NULL);//要回收的线程号,要回收的线程退出时的状态,NULL
 53     //销毁锁资源
 54     pthread_mutex_destroy(&mutex);//互斥锁指针
 55     return 0;
 56 }  

运行结果:

2.编程实现无名信号量

(1)生产和销售

程序代码:

  1 #include<myhead.h>
  2 //1.创建无名信号量
  3 sem_t sem;//定义一个sem_t类型的变量
  4 //定义生产线程
  5 void *task1(void *arg)
  6 {
  7     int num=5;//定义循环量
  8     while(num--)
  9     {
 10         sleep(1);
 11         printf("生产三蹦子\n");
 12         //4.释放资源
 13         sem_post(&sem);//释放无名信号量资源,value加1,
 14         //无名信号量地址
 15     }
 16     //退出线程
 17     pthread_exit(NULL);//线程退出时状态,NULL
 18 }
 19 //定义消费线程
 20 void *task2(void *arg)
 21 {
 22     int num=5;
 23     while(num--)
 24     {
 25         //3.申请资源
 26         sem_wait(&sem);//申请资源,value减1,为0时阻塞,无名信号量地址
 27         printf("消费三蹦子\n");
 28     }
 29     pthread_exit(NULL);
 30 }
 31 int main(int argc, const char *argv[])
 32 {
 33     //2.初始化无名信号量
 34     sem_init(&sem,0,0);
 35     //无名信号量地址,0线程间同步,当前无名信号量维护的value值初始值
 36     //创建两个线程,生产和消费
 37     pthread_t tid1,tid2;
 38     if(pthread_create(&tid1,NULL,task1,NULL)!=0)
 39     //线程号指针,线程属性,线程体(函数体),线程体的参数
 40     //成0败POSIX库中错误码,不能perror()
 41     {
 42         printf("tid1 create error\n");
 43         return 0;
 44     }
 45     if(pthread_create(&tid2,NULL,task2,NULL)!=0)
 46     {
 47         printf("tid2 create error\n");
 48         return 0;
 49     }
 50     printf("tid1:%#lx,tid2:%#lx\n",tid1,tid2);
 51     //回收线程资源
 52     pthread_join(tid1,NULL);//阻塞等待指定线程退出,收尸
 53     pthread_join(tid2,NULL);//要回收的线程号、要回收线程退出时状态
 54     //释放无名信号量
 55     sem_destroy(&sem);//无名信号量地址
 56     return 0;
 57 } 

运行结果:

(2)创建三个线程,线程1打印A,线程2打印B,线程3打印C

程序代码:

  1 #include<myhead.h>
  2 //创建无名信号量
  3 sem_t sem1,sem2,sem3;
  4 //定义线程1
  5 void *task1(void *arg)
  6 {
  7     int num=3;
  8     while(num--)
  9     {
 10         //3.申请资源
 11         sem_wait(&sem1);
 12         sleep(1);
 13         printf("A\t");
 14         //刷新给定文件指针缓冲区,要刷新的缓冲区
 15         //stdout标准输出指针
 16         fflush(stdout);
 17         //4.释放资源
 18         sem_post(&sem2);//释放无名信号量sem2的资源,value加1
 19     }
 20     //退出线程
 21     pthread_exit(NULL);
 22 }
 23 //定义线程2
 24 void *task2(void *arg)
 25 {
 26     int num=3;
 27     while(num--)
 28     {
 29         sem_wait(&sem2);//sem2资源-1
 30         sleep(1);
 31         printf("B\t");
 32         fflush(stdout);//输出没有\n,不刷新不会打印出来,等全部运行结束直接给出结果
 33         sem_post(&sem3);//sem3资源+1,sem3才能接着用
 34     }
 35     pthread_exit(NULL);
 36 }
 37 //定义线程3
 38 void *task3(void *arg)
 39 {
 40     int num=3;
 41     while(num--)
 42     {
 43         //申请资源sem3
 44         sem_wait(&sem3);
 45         sleep(1);
 46         printf("C\t");
 47         fflush(stdout);
 48         sem_post(&sem1);//释放sem1资源,
 49     }
 50     pthread_exit(NULL);
 51 }
 52 int main(int argc, const char *argv[])
 53 {
 54     //初始化无名信号量
 55     sem_init(&sem1,0,1);//无名信号量地址
 56     sem_init(&sem2,0,0);//0线程同步
 57     sem_init(&sem3,0,0);//初始资源为1,0
 58     //定义线程号变量
 59     pthread_t tid1,tid2,tid3;
 60     if(pthread_create(&tid1,NULL,task1,NULL)!=0)//创建线程分支
 61     {
 62         printf("tid1 create error\n");
 63         return 0;
 64     }
 65     if(pthread_create(&tid2,NULL,task2,NULL)!=0)//无名信号量地址,线程属性,线程体,线程体参数
 66     {
 67         printf("tid2 create error\n");
 68         return 0;
 69     }
 70     if(pthread_create(&tid3,NULL,task3,NULL)!=0)
 71     {
 72         printf("tid3 create error\n");
 73         return 0;
 74     }
 75     printf("tid1:%#lx,tid2:%#lx,tid3:%#lx\n",tid1,tid2,tid3);
 76     //回收线程资源
 77     pthread_join(tid1,NULL);
 78     pthread_join(tid2,NULL);
 79     pthread_join(tid3,NULL);
 80     //释放无名信号量
 81     sem_destroy(&sem1);
 82     sem_destroy(&sem2);
 83     sem_destroy(&sem3);
 84     puts("");
 85     return 0;
 86 }    

运行结果:

3.编程实现条件变量

程序代码:

  1 #include<myhead.h>
  2 //1.定义条件变量
  3 pthread_cond_t cond;
  4 //定义互斥锁变量
  5 pthread_mutex_t mutex;
  6 //定义生产线程
  7 void *task1(void *arg)
  8 {
  9     int num=5;
 10     while(num--)
 11     {
 12         sleep(1);
 13         printf("%#lx:生产三蹦子\n",pthread_self());
 14         //3.唤醒一个消费
 15     //  pthread_cond_signal(&cond);//条件变量地址
 16     }
 17     //3.唤醒所以的等待线程
 18     pthread_cond_broadcast(&cond);//条件变量地址
 19     //退出线程
 20     pthread_exit(NULL);
 21 }
 22 //定义消费线程
 23 void *task2(void *arg)
 24 {
 25     //上锁
 26     pthread_mutex_lock(&mutex);
 27     //进入等待队列
 28     pthread_cond_wait(&cond,&mutex);//条件变量指针,互斥锁变量地址
 29     //该函数内部实现
 30     //将当前线程放入休眠等待队列,释放锁资源
 31     //挂起,被其他线程唤醒后:自动获取锁资源
 32     printf("%#lx:消费三蹦子\n",pthread_self());
 33     //解锁
 34     pthread_mutex_unlock(&mutex);
 35     pthread_exit(NULL);
 36 }
 37 int main(int argc, const char *argv[])
 38 {
 39     //2.初始化条件变量
 40     pthread_cond_init(&cond,NULL);//条件变量指针,条件属性
 41     //初始化互斥锁
 42     pthread_mutex_init(&mutex,NULL);//互斥锁变量地址,互斥锁属性
 43     //创建两个线程,生产和消费
 44     pthread_t tid1,tid2,tid3,tid4,tid5,tid6;
 45     if(pthread_create(&tid1,NULL,task1,NULL)!=0)//线程号指针
 46     {
 47         printf("tid1 create error\n");//成0败非0错误码,不是置位错误码
 48         return 0;
 49     }
 50     if(pthread_create(&tid2,NULL,task2,NULL)!=0)//线程属性
 51     {
 52         printf("tid2 create error\n");
 53         return 0;
 54     }
 55     if(pthread_create(&tid3,NULL,task2,NULL)!=0)//线程体,函数指针
 56     {
 57         printf("tid3 create error\n");
 58         return 0;
 59     }
 60     if(pthread_create(&tid4,NULL,task2,NULL)!=0)//线程体的参数
 61     {
 62         printf("tid4 create error\n");
 63         return 0;
 64     }
 65     if(pthread_create(&tid5,NULL,task2,NULL)!=0)
 66     {
 67         printf("tid5 create error\n");
 68         return 0;
 69     }
 70     if(pthread_create(&tid6,NULL,task2,NULL)!=0)
 71     {
 72         printf("tid6 create error\n");
 73         return 0;
 74     }
 75     printf("tid1:%#lx,tid2:%#lx,tid3:%#lx,tid4:%#lx,tid5:%#lx,\
 76             tid6:%#lx\n",tid1,tid2,tid3,tid4,tid5,tid6);
 77     //回收线程资源
 78     pthread_join(tid1,NULL);//线程号,线程回收时状态
 79     pthread_join(tid2,NULL);
 80     pthread_join(tid3,NULL);
 81     pthread_join(tid4,NULL);
 82     pthread_join(tid5,NULL);
 83     pthread_join(tid6,NULL);
 84     //销毁条件变量
 85     pthread_cond_destroy(&cond);//条件变量指针
 86     //销毁互斥锁
 87     pthread_mutex_destroy(&mutex);//无名信号量地址
 88     return 0;
 89 }      

运行结果:

4.编程实现无名管道

程序代码:

  1 #include<myhead.h>
  2 int main(int argc, const char *argv[])
  3 {
  4     //创建管道文件,并返回该管道文件的文件描述符
  5     int pipefd[2]={0};//返回pipefd[0]读端,pipefd[1]写端
  6     if(pipe(pipefd)==-1)
  7     {
  8         perror("pipe error");
  9         return -1;
 10     }
 11     printf("pipe[0]=%d,pipe[1]=%d\n",pipefd[0],pipefd[1]);
 12     //创建子进程
 13     pid_t pid=fork();
 14     if(pid>0)
 15     {
 16         //父进程
 17         //关闭管道读端
 18         //创建管道文件放在创建子进程之前,否则各自创建一个管道,无意义
 19         //父进程、子进程都创建同一个管道描述符,
 20         //要关闭父进程的读端,子进程的写端
 21         close(pipefd[0]);//pipefd[0]    读
 22         char wbuf[128]="";
 23         while(1)
 24         {
 25             bzero(wbuf,sizeof(wbuf));//清空数组内容,
 26             //每次写入不同长度,写短了就会保留长的一部分
 27             fgets(wbuf,sizeof(wbuf),stdin);//终端输入数据
 28             wbuf[strlen(wbuf)-1]=0;//把读取的字符串,最后一个改为0,便于比较
 29             //将数据写入管道文件
 30             write(pipefd[1],wbuf,strlen(wbuf));//要操作的文件描述符,容器起始位置,读取大小
 31             //对写入数据判断
 32             if(strcmp(wbuf,"quit")==0)
 33                 break;
 34         }
 35         //关闭写端
 36         close(pipefd[1]);
 37         wait(NULL);//阻塞回收子进程资源
 38     }else if(pid==0)
 39     {
 40         //子进程
 41         //关闭写端
 42         close(pipefd[1]);
 43         char rbuf[128]="";
 44         while(1)
 45         {
 46             //清空rbuf内容
 47             bzero(rbuf,sizeof(rbuf));
 48             //从管道文件中读取数据
 49             read(pipefd[0],rbuf,sizeof(rbuf));
 50             //输出rbuf的数据
 51             printf("父进程传来数据:%s\n",rbuf);
 52             //对读取的数据判断
 53             if(strcmp(rbuf,"quit")==0)
 54                 break;
 55         }
 56         //关闭读端
 57         close(pipefd[0]);
 58         exit(EXIT_SUCCESS);//退出进程
 59     }else
 60     {
 61         perror("fork error");
 62         return -1;
 63     }
 64     return 0;
 65 }     

运行结果:

5.编程实现有名管道

程序代码:

create.c:

  1 #include<myhead.h>
  2 int main(int argc, const char *argv[])
  3 {
  4     //创建一个管道文件
  5     if(mkfifo("./myfifo",0664)==-1)
  6     {
  7         perror("mkfifo error");
  8         return -1;
  9     }
 10     getchar();//阻塞
 11     system("rm myfifo");
 12 
 13     return 0;
 14 }   

send.c:

  1 #include<myhead.h>
  2 int main(int argc, const char *argv[])
  3 {
  4     //打开管道文件
  5     int wfd=-1;
  6     //以只写形式打开
  7     if((wfd=open("./myfifo",O_WRONLY))=
  8     {
  9         perror("open error");
 10         return -1;
 11     }
 12     //定义容器
 13     char wbuf[128]="";
 14     while(1)
 15     {
 16         printf("请输入>>>");
 17         fgets(wbuf,sizeof(wbuf),stdin);
 18         wbuf[strlen(wbuf)-1]=0;
 19         //将数据写入管道
 20         write(wfd,wbuf,strlen(wbuf));
 21         //判断结果
 22         if(strcmp(wbuf,"quit")==0)
 23             break;
 24     }
 25     //关闭文件
 26     close(wfd);
 27     return 0;
 28 }   

rec.c:

  1 #include<myhead.h>
  2 int main(int argc, const char *argv[])
  3 {
  4     //打开管道文件
  5     int rfd=-1;
  6     //以只读形式打开
  7     if((rfd=open("./myfifo",O_RDONLY))=
  8     {
  9         perror("open error");
 10         return -1;
 11     }
 12     //定义容器
 13     char rbuf[128]="";
 14     while(1)
 15     {
 16         //清空数组
 17         bzero(rbuf,sizeof(rbuf));
 18         //读取管道中数据
 19         read(rfd,rbuf,sizeof(rbuf));
 20         //输出结果
 21         printf("收到数据:%s\n",rbuf);
 22         if(strcmp(rbuf,"quit")==0)
 23             break;
 24     }
 25     //关闭文件
 26     close(rfd);
 27     return 0;
 28 }    

运行结果:

6.使用有名管道完成两个进程的相互通信

程序代码:

01create:

  1 #include<myhead.h>
  2 int main(int argc, const char *argv[])
  3 {
  4     //创建两个管道文件
  5     if(mkfifo("./myfifo1",0664)==-1)
  6     {
  7         perror("myfifo1 create error");
  8         return -1;
  9     }
 10     if(mkfifo("./myfifo2",0664)==-1)
 11     {
 12         perror("myfifo2 create error");
 13         return -1;
 14     }
 15     printf("create success\n");
 16     getchar();//阻塞进程
 17     system("rm myfifo1 myfifo2");//删除两>
 18     return 0;
 19 }

01send.c:

  1 #include<myhead.h>
  2 int main(int argc, const char *argv[])
  3 {
  4     //两个进程,父进程给管道1写数据,子进程从管道2读取数据
  5     pid_t pid=-1;
  6     pid=fork();
  7     if(pid==0)
  8     {
  9         //子进程管道2读取数据
 10         int rfd=-1;
 11         if((rfd=open("./myfifo2",O_RDONLY))==-1)
 12         {
 13             perror("open myfifo2 error");
 14             return -1;
 15         }
 16         char buf[128]="";
 17         while(1)
 18         {
 19             bzero(buf,sizeof(buf));//清空数组
 20             read(rfd,buf,sizeof(buf));//从管道2读取数据
 21             printf("读取数据:%s\n",buf);
 22             if(strcmp(buf,"quit")==0)
 23                 break;
 24         }
 25         //关闭文件
 26         close(rfd);
 27         //退出进程
 28         exit(EXIT_SUCCESS);
 29     }else if(pid>0)
 30     {
 31         //父进程向管道1写数据
 32         int wfd=-1;
 33         if((wfd=open("./myfifo1",O_WRONLY))==-1)
 34         {
 35             perror("open myfifo1 error");
 36             return -1;
 37         }
 38         char buf[128]="";
 39         while(1)
 40         {
 41             bzero(buf,sizeof(buf));//清空数组
 42             fgets(buf,sizeof(buf),stdin);
 43             buf[strlen(buf)-1]=0;
 44             //将数据写入管道
 45             write(wfd,buf,strlen(buf));
 46             if(strcmp(buf,"quit")==0)
 47                 break;
 48         }
 49         //关闭文件
 50         close(wfd);
 51         //回收子进程资源
 52         wait(NULL);
 53     }else
 54     {
 55         perror("fork error");
 56         return -1;
 57     }
 58     return 0;
 59 }         

02send.c:

  1 #include<myhead.h>
  2 int main(int argc, const char *argv[])
  3 {
  4     //两个进程,父进程读取管道1数据,子进程写数据给管道2
  5     pid_t pid=-1;
  6     pid=fork();
  7     if(pid<0)
  8     {
  9         perror("fork error");
 10         return -1;
 11     }else if(pid==0)
 12     {
 13         //子进程写数据给管道2
 14         int wfd=-1;
 15         if((wfd=open("./myfifo2",O_WRONLY))==-1)
 16         {
 17             perror("open myfifo2 error");
 18             return -1;
 19         }
 20         char buf[128]="";
 21         while(1)
 22         {
 23             bzero(buf,sizeof(buf));//清空数组
 24             fgets(buf,sizeof(buf),stdin);
 25             buf[strlen(buf)-1]=0;
 26             //写入数据
 27             write(wfd,buf,strlen(buf));
 28             if(strcmp(buf,"quit")==0)
 29                 break;
 30         }
 31         //关闭文件
 32         close(wfd);
 33         //退出进程
 34         exit(EXIT_SUCCESS);
 35     }else
 36     {
 37         //父进程读取管道1
 38         int rfd=-1;
 39         if((rfd=open("./myfifo1",O_RDONLY))==-1)
 40         {
 41             perror("open myfifo1 error");
 42             return -1;
 43         }
 44         char buf[128]="";
 45         while(1)
 46         {
 47             bzero(buf,sizeof(buf));
 48             //读取数据
 49             read(rfd,buf,sizeof(buf));
 50             printf("读取数据:%s\n",buf);                             
 51             if(strcmp(buf,"quit")==0)
 52                 break;
 53         }
 54         //关闭文件
 55         close(rfd);
 56         wait(NULL);//回收子进程资源
 57     }
 58     return 0;
 59 }

运行结果:

流程图:

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

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

相关文章

【前端素材】推荐优质后台管理系统GramOs平台模板(附源码)

一、需求分析 后台管理系统是一种用于管理网站、应用程序或系统的工具&#xff0c;它通常作为一个独立的后台界面存在&#xff0c;供管理员或特定用户使用。下面详细分析后台管理系统的定义和功能&#xff1a; 1. 定义 后台管理系统是一个用于管理和控制网站、应用程序或系统…

git切换仓库地址

已有git仓库&#xff0c;要切换提交的仓库地址&#xff0c;用以下命令 git remote set-url origin 自己的仓库地址 用以下命令&#xff0c;查看当前仓库地址&#xff1a; git remote show origin 切换仓库后&#xff0c;用以下命令初始化提交仓库&#xff1a; git push -u o…

cocos creator3.x项目打包成aar 加入到已有的Android工程

Cocos crearor版本&#xff1a; 3.4.2 Android Studio Flamingo | 2022.2.1 Patch 2 1、配置构建安卓项目 2、 运行编译无报错 出现问题可尝试修改Gradle版本 修改jdk版本 3、对libservice打包成aar 打包完后 再build/outputs找到aar 如果看不到Tasks模块&#xff0c;在Fil…

连接查询(学习笔记)

通过对DQL的学习&#xff0c;我们可以很轻松的从一张数据表中查询出需要的数据&#xff1b;在企业的应用开发中&#xff0c;我们经常需要从多张表中查询数据&#xff08;例如&#xff1a;我们查询学生信息的时候需要同时查询学生的班级信息&#xff09;&#xff0c;可以通过连接…

【Spring】IoC容器 控制反转 与 DI依赖注入 概念 第一期

文章目录 Spring 和 SpringFramework概念一、Spring IoC容器 核心概念1.1 组件和组件管理概念1.2 Spring IoC容器和容器实现1.2.1 普通和复杂容器1.2.2 SpringIoC容器介绍1.2.3 SpringIoC容器具体接口和实现类1.2.4 SpringIoC容器管理配置方式 1.3 Spring IoC / DI概念总结二、…

Electron实战之环境搭建

工欲善其事必先利其器&#xff0c;在进行实战开发的时候&#xff0c;我们最终的步骤是搞好一个舒服的开发环境&#xff0c;目前支持 Vue 的 Electron 工程化工具主要有 electron-vue、Vue CLI Plugin Electron Builder、electron-vite。 接下来我们将分别介绍基于 Vue CLI Plu…

DataDreamer:让创建自定义数据集轻松无比!还自带标注!

编辑&#xff1a;OAK中国 首发&#xff1a;oakchina.cn 喜欢的话&#xff0c;请多多&#x1f44d;⭐️✍ 内容可能会不定期更新&#xff0c;官网内容都是最新的&#xff0c;请查看首发地址链接。 ▌前言 Hello&#xff0c;大家好&#xff0c;这里是OAK中国&#xff0c;我是Ash…

数字信号处理:傅里叶分析

本文主要参考视频如下&#xff1a; 数字信号处理9-1_线性时不变系统对复指数信号的响应_哔哩哔哩_bilibili 傅里叶分析的主要研究内容如下所示&#xff1a; 注意&#xff0c;计算机中使用的离散傅里叶变换并不是离散时间傅里叶变换&#xff1b; 前四种都是理论上的变换方式&…

Graphpad Prism10.2.0(329) 安装教程 (含Win/Mac版)

GraphPad Prism GraphPad Prism是一款非常专业强大的科研医学生物数据处理绘图软件&#xff0c;它可以将科学图形、综合曲线拟合&#xff08;非线性回归&#xff09;、可理解的统计数据、数据组织结合在一起&#xff0c;除了最基本的数据统计分析外&#xff0c;还能自动生成统…

springboot大学生体质测试管理系统源码和论文

大学生体质测试管理系统提供给用户一个简单方便体质测试管理信息&#xff0c;通过留言区互动更方便。本系统采用了B/S体系的结构&#xff0c;使用了java技术以及MYSQL作为后台数据库进行开发。系统主要分为系统管理员、教师和用户三个部分&#xff0c;系统管理员主要功能包括首…

vue-router 三级路由,路由跳转页面异常白屏或404,或刷新三级路由页面后一级和二级路由菜单丢失

问题描述 情况1. vue-router 定义三级路由&#xff0c;路由跳转了&#xff0c;页面404或者白屏情况2. 点击菜单三级路由后&#xff0c;刷新页面后一级和二级路由菜单丢失 解决方案&#xff1a; 某些时候是因为二级和三级的路由共用router-view&#xff0c;可以使用router-vi…

【MySQL系列 04】深入浅出索引

一、索引介绍 提到数据库索引&#xff0c;相信大家都不陌生&#xff0c;在日常工作中会经常接触到。比如某一个 SQL 查询比较慢&#xff0c;分析完原因之后&#xff0c;你可能就会说“给某个字段加个索引吧”之类的解决方案。 但到底什么是索引&#xff0c;索引又是如何工作的…

Vue | (四)使用Vue脚手架(上) | 尚硅谷Vue2.0+Vue3.0全套教程

文章目录 &#x1f4da;初始化脚手架&#x1f407;创建初体验&#x1f407;分析脚手架结构&#x1f407;关于render&#x1f407;查看默认配置 &#x1f4da;ref与props&#x1f407;ref属性&#x1f407;props配置项 &#x1f4da;混入&#x1f4da;插件&#x1f4da;scoped样…

抖音爬虫批量视频提取功能介绍|抖音评论提取工具

抖音爬虫是指通过编程技术从抖音平台上获取视频数据的程序。在进行抖音爬虫时&#xff0c;需要注意遵守相关法律法规和平台规定&#xff0c;以确保数据的合法获取和使用。 一般来说&#xff0c;抖音爬虫可以实现以下功能之一&#xff1a;批量视频提取。这个功能可以用于自动化地…

Lua速成(2)

一、流程控制 Lua 编程语言流程控制语句通过程序设定一个或多个条件语句来设定。在条件为 true 时执行指定程序代码&#xff0c;在条件为 false 时执行其他指定代码。 控制结构的条件表达式结果可以是任何值&#xff0c;Lua认为false和nil为假&#xff0c;true和非nil为真。 …

模拟、排序(归并排序)算法

模拟、排序算法 一、模拟例题1、错误票据题目信息思路题解 2、回文日期题目信息思路方法一&#xff1a;暴力做法方法二&#xff1a;优化解法 题解方法一&#xff1a;暴力求解方法二&#xff1a;优化解法 二、排序例题1、归并排序题目信息思路题解 一、模拟 例题 1、错误票据 …

AI副业项目分享

在上一篇文章《这才是大学生该做的副业&#xff0c;别再痴迷于游戏了&#xff01;》中&#xff0c;我分享了一些副业的想法&#xff0c;接着有不少同学问我&#xff1a;具体如何做&#xff1f;这是真把我给整蒙了&#xff0c;这里分享下我可以提供的产品和服务吧&#xff0c;并…

实用区块链应用:去中心化投票系统的部署与实施

一、需求分析背景 随着技术的发展&#xff0c;传统的投票系统面临着越来越多的挑战&#xff0c;如中心化控制、透明度不足和易受攻击等问题。为了解决这些问题&#xff0c;我们可以利用区块链技术去中心化、透明性和安全性来构建一个去中心化投票系统。这样的系统能够确保投票过…

【某机构vip教程】python(6):python读取ini的配置文件

python读取ini的配置文件 configparser模块简介&#xff1a; configparser模块是用来解析ini配置文件的解析器。 ini配置文件的结构如x下图 ini文件结构需要注意以下几点&#xff1a; 键值对可用或者:进行分隔 section的名字是区分大小写的,而key的名字是不区分大小写的 …

Redis(十五)Bitmap、Hyperloglog、GEO案例、布隆过滤器

文章目录 面试题常见统计类型聚合统计排序统计二值统计基数统计 Hyperloglog专有名词UV&#xff08;Unique Visitor&#xff09;独立访客PV&#xff08;Page View&#xff09;页面浏览量DAU&#xff08;Daily Active User&#xff09;日活跃用户量MAU&#xff08;Monthly Activ…