Linux系统编程——线程的学习
学习参考博文:
 Linux多线程编程初探
Linux系统编程学习相关博文
- Linux系统编程——文件编程的学习
 - Linux系统编程——进程的学习
 - Linux系统编程——进程间通信的学习
 - Linux系统编程——网络编程的学习
 
Linux系统编程——线程的学习
- 一、概述
 - 1. 进程与线程的区别
 - 2. 使用线程的理由
 - 3. 互斥量
 - 4. 条件变量
 
- 二、线程API
 - 三、API介绍
 - 1. pthread_creat函数
 - 2. pthread_exit函数
 - 3. pthread_join函数
 - 4. pthread_self函数
 - 5. pthread_mutex_inti函数
 - 6. pthread_mutex_destroy函数
 - 7. pthread_mutex_lock函数
 - 8. pthread_mutex_unlock函数
 - 9. pthread_cond_init函数
 - 10. pthread_cond_destroy函数
 - 11. pthread_cond_wait函数
 - 12. pthread_cond_signal函数
 
- 四、API的使用例子
 - 1. pthread_creat、pthread_exit、pthread_join、pthread_self函数
 - 2. pthread_mutex_init、pthread_mutex_destory、pthread_mutex_lock、pthread_mutex_unlock函数
 - 3. pthread_cond_init、pthread_cond_destory、pthread_cond_wait、pthread_cond_signal函数
 
一、概述
常规学习Linux系统编程的内容是复杂且繁多的,不推荐刚开始接触代码的朋友去学习,所以介绍Linux系统编程的目的主要是以应用开发为主。
1. 进程与线程的区别
- 进程——资源分配的最小单位,线程——程序执行的最小单位
 - 在面向线程设计的系统中,进程本身不是基本运行单位,而是线程的容器。程序本身只是指令、数据及其组织形式的描述,进程才是程序 (那些指令和数据) 的真正运行实例。(程序是静态的,进程是动态的)
 - 一个进程里边可以有多个线程。进程的所有信息对该进程的所有线程都是共享的,包括可执行的程序文本、程序的全局内存和堆内存、栈以及文件描述符。
 - 进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。
 - 总的来说:进程有独立的地址空间,线程没有单独的地址空间(同一进程内的线程共享进程的地址空间)。
 
2. 使用线程的理由
- 使用多线程的理由之一是和进程相比,它是一种非常"节俭"的多任务操作方式。我们知道,在Linux系统下,启动一个新的进程必须分配给它独立的地址空间,建立众多的数据表来维护它的代码段、堆栈段和数据段,这是一种"昂贵"的多任务工作方式。而运行于一个进程中的多个线程,它们彼此之间使用相同的地址空间,共享大部分数据,启动一个线程所花费的空间远远小于启动一个进程所花费的空间,而且,线程间彼此切换所需的时间也远远小于进程间切换所需要的时间。据统计,总的说来,一个进程的开销大约是一个线程开销的30倍左右,当然,在具体的系统上,这个数据可能会有较大的区别。
 - 使用多线程的理由之二是线程间方便的通信机制。对不同进程来说,它们具有独立的数据空间,要进行数据的传递只能通过通信的方式进行,这种方式不仅费时,而且很不方便。线程则不然,由于同一进程下的线程之间共享数据空间,所以一个线程的数据可以直接为其它线程所用,这不仅快捷,而且方便。当然,数据的共享也带来其他一些问题,有的变量不能同时被两个线程所修改,有的子程序中声明为static的数据更有可能给多线程程序带来灾难性的打击,这些正是编写多线程程序时最需要注意的地方。
 
3. 互斥量
- 互斥量(mutex)从本质上来说是一把锁,在访问共享资源前对互斥量进行加锁,在访问完成后释放互斥量上的锁。对互斥量进行加锁后,任何其他试图再次对互斥量加锁的线程将会被阻塞直到当前线程释放该互斥锁。如果释放互斥锁时有多个线程阻塞,所有在该互斥锁上的阻塞线程都会变成可运行状态,第一个变为可运行状态的线程可以对互斥量加锁,其他线程将会看到互斥锁依然被锁住,只能回去等待它重新变为可用。在这种方式下,每次只有一个线程可以向前运行。
 - 在设计时需要规定所有的线程必须遵守相同的数据访问规则。只有这样,互斥机制才能正常工作。操作系统并不会做数据访问的串行化。如果允许其中的某个线程在没有得到锁的情况下也可以访问共享资源,那么即使其它的线程在使用共享资源前都获取了锁,也还是会出现数据不一致的问题。
 - 互斥变量用pthread_mutex_t数据类型表示。在使用互斥变量前必须对它进行初始化,可以把它置为常量PTHREAD_MUTEX_INITIALIZER(只对静态分配的互斥量),也可以通过调用pthread_mutex_init函数进行初始化。如果动态地分配互斥量(例如通过调用malloc函数),那么在释放内存前需要调用pthread_mutex_destroy。
 
4. 条件变量
- 条件变量是线程另一可用的同步机制。条件变量给多个线程提供了一个会合的场所。条件变量与互斥量一起使用时,允许线程以无竞争的方式等待特定的条件发生。
 - 条件本身是由互斥量保护的。线程在改变条件状态前必须首先锁住互斥量,其他线程在获得互斥量之前不会察觉到这种改变,因为必须锁定互斥量以后才能计算条件。
 - 条件变量使用之前必须首先初始化,pthread_cond_t数据类型代表的条件变量可以用两种方式进行初始化,可以把常量PTHREAD_COND_INITIALIZER赋给静态分配的条件变量,但是如果条件变量是动态分配的,可以使用pthread_cond_destroy函数对条件变量进行去除初始化(deinitialize)。
 
二、线程API
在Linux系统中,操作系统提供了一系列的API,详细看下图
1. 线程
创建		pthread_creat()
退出		pthread_exit()
等待		pthread_join()
获取ID		pthread_self()
2. 互斥锁
创建		pthread_mutex_init()
销毁		pthread_mutex_destroy()
加锁		pthread_mutex_lock()
解锁		pthread_mutex_unlock()
3. 条件
创建		pthread_cond_init()
销毁		pthread_cond_destroy()
触发		pthread_cond_signal()
广播		pthread_cond_broadcast()
等待		pthread_cond_wait() / pthread_cond_timewait()
 
三、API介绍
1. pthread_creat函数
#include <pthread.h>int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);1. 函数功能:创建线程
2. 形参说明:
tidp:线程ID
attr:线程属性。暂可以把它设置为NULL,以创建默认属性的线程。
start_rtn:新创建线程的运行函数
arg:函数运行传递的参数
3. 返回值:成功返回0,失败返回错误编号
 
2. pthread_exit函数
#include <pthread.h>int pthread_exit(void *rval_ptr);1. 函数功能:线程退出
2. 形参说明:
rival_ptr:退出时返回的数据
 
3. pthread_join函数
#include <pthread.h>int pthread_join(pthread_t thread, void **rval_ptr);1. 函数功能:调用这个函数的线程将一直阻塞,直到指定的线程调用pthread_exit、从启动例程中返回或者被取消。
2. 形参说明:
thread:线程ID
rival_ptr:线程退出时返回的数据
3. 返回值:成功返回0,失败返回错误编号
 
4. pthread_self函数
#include <pthread.h>pthread_t pthread_self(void);1. 函数功能:获取线程ID
2. 返回值:调用线程的ID
 
5. pthread_mutex_inti函数
#include <pthread.h>int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);1. 函数功能:创建互斥锁
2. 形参说明:
mutex:锁ID
attr:锁的属性。默认的属性初始化互斥量,只需把attr设置为NULL。
3. 返回值:成功返回0,失败返回错误编号
 
6. pthread_mutex_destroy函数
#include <pthread.h>int pthread_mutex_destroy(pthread_mutex_t *mutex);1. 函数功能:销毁互斥锁
2. 形参说明:
mutex:锁ID
3. 返回值:成功返回0,失败返回错误编号
 
7. pthread_mutex_lock函数
#include <pthread.h>int pthread_mutex_lock(pthread_mutex_t *mutex);1. 函数功能:加锁
2. 形参说明:
mutex:锁ID
3. 返回值:成功返回0,失败返回错误编号
 
8. pthread_mutex_unlock函数
#include <pthread.h>int pthread_mutex_unlock(pthread_mutex_t *mutex);1. 函数功能:解锁
2. 形参说明:
mutex:锁ID
3. 返回值:成功返回0,失败返回错误编号
 
9. pthread_cond_init函数
#include <pthread.h>int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);1. 函数功能:创建条件变量
2. 形参说明:
cond:条件ID
attr:条件属性。除非需要创建一个非默认属性的条件变量,否则该参数可以设置为NULL。
3. 返回值:成功返回0,失败返回错误编号
 
10. pthread_cond_destroy函数
#include <pthread.h>int pthread_cond_destroy(pthread_cond_t *cond);1. 函数功能:销毁条件变量
2. 形参说明:
cond:条件ID
3. 返回值:成功返回0,失败返回错误编号
 
11. pthread_cond_wait函数
#include <pthread.h>int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);1. 函数功能:等待条件为真
2. 形参说明:
cond:条件ID
mutex:锁ID
3. 返回值:成功返回0,失败返回错误编号
 
12. pthread_cond_signal函数
#include <pthread.h>int pthread_cond_signal(pthread_cond_t *cond);1. 函数功能:触发条件
2. 形参说明:
cond:条件ID
3. 返回值:成功返回0,失败返回错误编号
 
四、API的使用例子
1. pthread_creat、pthread_exit、pthread_join、pthread_self函数
  1 #include <stdio.h>2 #include <stdlib.h>3 #include <string.h>4 5 #include <pthread.h>6 7 // 1. int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*    start_rtn)(void *), void *restrict arg);8 // 2. pthread_t pthread_self(void);9 // 3. int pthread_join(pthread_t thread, void **rval_ptr);10 // 4. int pthread_exit(void *rval_ptr);11 12 void *func1(void *arg)13 {14     static int data = 10;15 16     printf("t1: %ld\n", pthread_self()); //打印线程ID17     printf("t1: arg = %d\n", *((int *)arg)); //打印传递的参数18 19     pthread_exit((void *)(&data)); //线程退出并返回数据20 }21 22 int main()23 {24     int ret = 0;25     int param = 100;26     int *pret = NULL;27 28     pthread_t t1; //线程ID29 30     ret = pthread_create(&t1, NULL, func1, (void *)¶m); //创建线程31 32     if(ret == 0){33         printf("main: %ld, pthread create success\n", pthread_self());34     }35 36     pthread_join(t1, (void **)(&pret)); //等待线程退出37 38     printf("main: pret = %d\n", *pret); //打印线程退出时反馈的的数据39 40     return 0;41 }
 
2. pthread_mutex_init、pthread_mutex_destory、pthread_mutex_lock、pthread_mutex_unlock函数
  1 #include <stdio.h>2 #include <stdlib.h>3 #include <string.h>4 5 #include <pthread.h>6 7 // 1. int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restric    t attr);8 // 2. int pthread_mutex_destroy(pthread_mutex_t *mutex);9 // 3. int pthread_mutex_lock(pthread_mutex_t *mutex);10 // 4. int pthread_mutex_unlock(pthread_mutex_t *mutex);11 12 int g_data = 0;13 14 pthread_mutex_t mutex; //锁15 16 void *func1(void *arg)17 {18     printf("t1: %ld\n", pthread_self()); //打印线程ID19     printf("t1: arg = %d\n", *((int *)arg)); //打印传递过来的数据20 21     pthread_mutex_lock(&mutex); //加锁22 23     while(1){24         printf("t1: %d\n", g_data++);25 26         if(g_data == 3){27             printf("t1 quit===========================\n");28             pthread_mutex_unlock(&mutex); //当g_data = 3时解锁29             pthread_exit(NULL); //线程退出30         }31 32         sleep(1);33     }34 35 }36 37 void *func2(void *arg)38 {39     printf("t2: %ld\n", pthread_self());40     printf("t2: arg = %d\n", *((int *)arg));41 42     while(1){43         pthread_mutex_lock(&mutex); //加锁44 45         printf("t2: %d\n", g_data++);46 47         pthread_mutex_unlock(&mutex); //解锁48 49         sleep(1);50     }51 }52 53 int main()54 {55     int ret = 0;56     int param = 100;57 58     pthread_t t1;59     pthread_t t2;60 61     pthread_mutex_init(&mutex, NULL); //创建互斥锁62 63     ret = pthread_create(&t1, NULL, func1, (void *)¶m); //创建线程164 65     if(ret == 0){66         //printf("main: t1:%ld, pthread create success\n", pthread_self());67     }68 69     ret = pthread_create(&t2, NULL, func2, (void *)¶m); //创建线程270 71     if(ret == 0){72         //printf("main: t2:%ld, pthread create success\n", pthread_self());73     }74 75     pthread_join(t1, NULL); //等待线程1退出76     pthread_join(t2, NULL); //等待线程2退出77 78     pthread_mutex_destroy(&mutex); //销毁互斥锁79 80     return 0;81 }
 
3. pthread_cond_init、pthread_cond_destory、pthread_cond_wait、pthread_cond_signal函数
1. 动态初始化
  1 #include <stdio.h>2 #include <stdlib.h>3 #include <string.h>4 5 #include <pthread.h>6 7 // 1. int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*    start_rtn)(void *), void *restrict arg);8 // 2. pthread_t pthread_self(void);9 // 3. int pthread_join(pthread_t thread, void **rval_ptr);10 // 4. int pthread_exit(void *rval_ptr);11 // 5. int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mut    exattr_t *res    trict attr);12 // 6. int pthread_mutex_destroy(pthread_mutex_t *mutex);13 // 7. int pthread_mutex_lock(pthread_mutex_t *mutex);14 // 8. int pthread_mutex_unlock(pthread_mutex_t *mutex);15 // 9. int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict at    tr);16 // 10. int pthread_cond_destroy(pthread_cond_t *cond);17 // 11. int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);18 // 12. int pthread_cond_signal(pthread_cond_t *cond);19 20 int g_data = 0;21 22 pthread_cond_t cond; //条件变量23 pthread_mutex_t mutex; //锁24 25 void *func1(void *arg)26 {27     printf("t1: %ld\n", pthread_self()); //打印线程ID28     printf("t1: arg = %d\n", *((int *)arg)); //打印传递过来的数据29 30     while(1){31         pthread_cond_wait(&cond, &mutex); //等待条件为真32 33         printf("t1 run=========================\n");34         printf("t1: %d\n", g_data);35         g_data = 0;36 37         sleep(1);38     }39 }40 41 void *func2(void *arg)42 {43     printf("t2: %ld\n", pthread_self());44     printf("t2: arg = %d\n", *((int *)arg));45 46     while(1){47         pthread_mutex_lock(&mutex); //加锁48 49         printf("t2: %d\n", g_data++);50         if(g_data == 3){51             pthread_cond_signal(&cond); //当g_data = 3时,触发条件,唤醒等待该条件的线程52         }53 54         pthread_mutex_unlock(&mutex); //解锁55 56         sleep(1);57     }58 }59 60 int main()61 {62     int ret = 0;63     int param = 100;64 65     pthread_t t1;66     pthread_t t2;67 68     pthread_cond_init(&cond, NULL); //创建条件变量69     pthread_mutex_init(&mutex, NULL); //创建互斥锁70 71     ret = pthread_create(&t1, NULL, func1, (void *)¶m); //创建线程172 73     if(ret == 0){74         //printf("main: t1:%ld, pthread create success\n", pthread_self());75     }76 77     ret = pthread_create(&t2, NULL, func2, (void *)¶m); //创建线程278 79     if(ret == 0){80         //printf("main: t2:%ld, pthread create success\n", pthread_self());81     }82 83     pthread_join(t1, NULL); //等待线程1退出84     pthread_join(t2, NULL); //等待线程2退出85 86     pthread_cond_destroy(&cond); //销毁条件变量87     pthread_mutex_destroy(&mutex); //销毁互斥锁88 89     return 0;90 }
 
2. 静态初始化
  1 #include <stdio.h>2 #include <stdlib.h>3 #include <string.h>4 5 #include <pthread.h>6 7 // 1. int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*    start_rtn)(void *), void *restrict arg);8 // 2. pthread_t pthread_self(void);9 // 3. int pthread_join(pthread_t thread, void **rval_ptr);10 // 4. int pthread_exit(void *rval_ptr);11 // 5. int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mut    exattr_t *res    trict attr);12 // 6. int pthread_mutex_destroy(pthread_mutex_t *mutex);13 // 7. int pthread_mutex_lock(pthread_mutex_t *mutex);14 // 8. int pthread_mutex_unlock(pthread_mutex_t *mutex);15 // 9. int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict at    tr);16 // 10. int pthread_cond_destroy(pthread_cond_t *cond);17 // 11. int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);18 // 12. int pthread_cond_signal(pthread_cond_t *cond);19 20 int g_data = 0;21 22 pthread_cond_t cond = PTHREAD_COND_INITIALIZER; //初始化条件变量23 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; //初始化互斥锁24 25 void *func1(void *arg)26 {27     printf("t1: %ld\n", pthread_self()); //打印线程ID28     printf("t1: arg = %d\n", *((int *)arg)); //打印传递过来的值29 30     while(1){31         pthread_cond_wait(&cond, &mutex); //等待条件为真32 33         printf("t1 run=========================\n");34         printf("t1: %d\n", g_data);35         g_data = 0;36 37         sleep(1);38     }39 }40 41 void *func2(void *arg)42 {43     printf("t2: %ld\n", pthread_self()); //打印线程ID44     printf("t2: arg = %d\n", *((int *)arg)); //打印传递过来的值45 46     while(1){47         pthread_mutex_lock(&mutex); //加锁48 49         printf("t2: %d\n", g_data++);50         if(g_data == 3){51             pthread_cond_signal(&cond); //当g_data = 3时,触发条件,唤醒等待该条件的线程52         }53 54         pthread_mutex_unlock(&mutex); //解锁55 56         sleep(1);57     }58 }59 60 int main()61 {62     int ret = 0;63     int param = 100;64 65     pthread_t t1;66     pthread_t t2;67 68     //pthread_cond_init(&cond, NULL);69     //pthread_mutex_init(&mutex, NULL);70 71     ret = pthread_create(&t1, NULL, func1, (void *)¶m); //创建线程172 73     if(ret == 0){74         //printf("main: t1:%ld, pthread create success\n", pthread_self());75     }76 77     ret = pthread_create(&t2, NULL, func2, (void *)¶m); //创建线程278 79     if(ret == 0){80         //printf("main: t2:%ld, pthread create success\n", pthread_self());81     }82 83     pthread_join(t1, NULL); //等待线程1退出84     pthread_join(t2, NULL); //等待线程2退出85 86     pthread_cond_destroy(&cond); //销毁条件变量87     pthread_mutex_destroy(&mutex); //销毁互斥锁88 89     return 0;90 }
相关文章:
Linux系统编程——线程的学习
学习参考博文: Linux多线程编程初探 Linux系统编程学习相关博文 Linux系统编程——文件编程的学习Linux系统编程——进程的学习Linux系统编程——进程间通信的学习Linux系统编程——网络编程的学习 Linux系统编程——线程的学习 一、概述1. 进程与线程的区别2. 使…...
zemaxMIF曲线图
调制传递函数( Modulation Transfer Function,MTF )是用来形容光学系统成像质量的重要指标。 通过对光学系统像空间进行傅里叶变换,可以得到一张分析图表,来描述像面上对比度和空间频率之间的对应关系。 对比度&…...
【苹果】SpringBoot监听Iphone15邮件提醒,Selenium+Python自动化抢购脚本
前言 🍊缘由 Iphone15来了,两年之约你还记得吗? 两年前,与特别的人有一个特别的约定。虽物是人非,但思念仍在。 遂整合之前iphone13及iphone14的相关抢购代码,完成一个SpringBoot监听Iphone15有货邮件提…...
什么是WhatsApp群发,WhatsApp协议,WhatsApp云控
那么WhatsApp群控云控可以做什么呢? 1、获客 自动化引流,强大的可控性,产品快速拓客 2、导流 一键式傻瓜化自动加好友,群发,朋友圈营销 3、群控 一键式拉群好友,建群,进群 …...
RealVNC viewer 窗口指定默认显示
RealVNC Viewer关于显示器(monitor)的参数有两个,一个是monitor,一个是useallmonitor。 monitor就是指定viewer窗体在哪个显示器上显示的,windows下的默认值是空白,改为\\.\DISPLAY2 就可以在打开远程窗口的时候默认在副屏上显…...
图论20(Leetcode1254.统计封闭岛屿的数目)
代码: class Solution {static int[][] dirs {{1,0},{-1,0},{0,1},{0,-1}};public int closedIsland(int[][] grid) {int num 0; for(int i0;i<grid.length;i){for(int j0;j<grid[0].length;j){if(grid[i][j]0){int[] start {i,j};if(getIsland(start,gri…...
Docker 的基本概念和优势,以及在应用程序开发中的实际应用
Docker是一种开源的容器化平台,它可以将应用程序打包成容器,并且可以在不同的环境中运行。Docker的基本概念包括: 镜像(Image):Docker镜像是一个可执行的包,它包含了运行应用程序所需的所有文件…...
数据仓库整理
数仓 olap vs oltp OLTP主要用于支持日常的业务操作,如银行交易、电子商务等,强调数据的准确性、实时性和并发性。OLAP主要用于支持复杂的数据分析,如数据仓库、决策支持等,强调数据的维度、聚合和可视化。 将OLTP数据库的数据…...
《C++API设计》读书笔记(3):模式
本章内容 本章涵盖了一些与CAPI设计相关的设计模式和惯用法。 “设计模式(Design Pattern)”表示软件设计问题的一些通用解决方案。该术语来源于《设计模式:可复用面向对象软件的基础》(Design Patterns: Elements of Reusable Object-Oriented Softwar…...
小程序搜索词优化:小陈运营的秘密武器
大家好,我是小陈,今天要和大家分享一下小程序搜索词优化的经验和技巧。在数字化时代,小程序已经成为许多企业的重要工具,但要让小程序在竞争激烈的市场中脱颖而出,搜索词优化是不可或缺的一环。在本文中,我…...
SpringSecurity 入门
文章目录 Spring Security概念快速入门案例环境准备Spring配置文件SpringMVC配置文件log4j配置文件web.xmlTomcat插件 整合SpringSecurity 认证操作自定义登录页面关闭CSRF拦截数据库认证加密认证状态记住我授权注解使用标签使用 Spring Security概念 Spring Security是Spring…...
【每日一题Day335】LC1993树上的操作 | dfs
树上的操作【LC1993】 给你一棵 n 个节点的树,编号从 0 到 n - 1 ,以父节点数组 parent 的形式给出,其中 parent[i] 是第 i 个节点的父节点。树的根节点为 0 号节点,所以 parent[0] -1 ,因为它没有父节点。你想要设计…...
FPGA:卷积编码及维特比译码仿真
FPGA:卷积编码及维特比译码仿真 本篇记录一下在FPGA中完成卷积编码和维特比译码的过程,通过代码解释编码的过程和译码的过程,便于理解,同时也方便移植到其他工程中。 1. 准备工作 卷积编译码IP核—convolutionIP核和viterbiIP核…...
MySQL学习笔记4
客户端工具的使用: MySQL: mysql命令行工具,一般用来连接访问mysql的数据。 案例:使用mysql客户端工具连接服务器端(用户名:root;密码:123456). [rootmysql-server ~]#…...
JavaFX:窗体显示状态,模态非模态
程序窗体显示一般有3中模式。非模态和模态,其中模态又分为程序模态和窗体模态。 非模态可以理解为窗体之间没有任何限制,可以用鼠标、键盘等工具在窗体间切换。 程序模态是窗体打开后,该程序的所有窗体都被冻结,无法切换&#x…...
C++17中std::filesystem::path的使用
C17引入了std::filesystem库(文件系统库, filesystem library)。这里整理下std::filesystem::path的使用。 std::filesystem::path,文件系统路径,提供了对文件系统及其组件(例如路径、常规文件和目录)执行操作的工具。此path类主要用法包括&#x…...
命令模式简介
概念: 命令模式是一种行为设计模式,它将请求封装成一个对象,从而允许您将不同的请求参数化、队列化,并且能够在不同的时间点执行。通过引入命令对象(Command)来解耦发送者(Invoker)…...
Boost序列化指针
Boost.Serialization 还能序列化指针和引用。 由于指针存储对象的地址,序列化对象的地址没有什么意义,而是在序列化指针和引用时,对象的引用被自动地序列化。 代码 #include <boost/archive/text_oarchive.hpp> #include <boost/…...
NIO简单介绍
一、什么是NIO 1、Java NIO全称java non-blocking IO, 是指JDK提供的新API。从JDK1.4开始,Java提供了一系列改进的输入/输出的新特性,被统称为NIO(即New IO),是同步非阻塞的 2、NIO有三大核心部分: Channel(通道), Buf…...
linux进程杀不死
项目场景: 虚拟机 问题描述 linux进程杀不死 无反应 原因分析: 进程僵死zombie 解决方案: 进proc或者find命令找到进程所在地址 cat status查看进程杀死子进程...
conda相比python好处
Conda 作为 Python 的环境和包管理工具,相比原生 Python 生态(如 pip 虚拟环境)有许多独特优势,尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处: 一、一站式环境管理:…...
基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真
目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销,平衡网络负载,延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...
为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?
在建筑行业,项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升,传统的管理模式已经难以满足现代工程的需求。过去,许多企业依赖手工记录、口头沟通和分散的信息管理,导致效率低下、成本失控、风险频发。例如&#…...
【单片机期末】单片机系统设计
主要内容:系统状态机,系统时基,系统需求分析,系统构建,系统状态流图 一、题目要求 二、绘制系统状态流图 题目:根据上述描述绘制系统状态流图,注明状态转移条件及方向。 三、利用定时器产生时…...
Reasoning over Uncertain Text by Generative Large Language Models
https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...
什么是VR全景技术
VR全景技术,全称为虚拟现实全景技术,是通过计算机图像模拟生成三维空间中的虚拟世界,使用户能够在该虚拟世界中进行全方位、无死角的观察和交互的技术。VR全景技术模拟人在真实空间中的视觉体验,结合图文、3D、音视频等多媒体元素…...
【免费数据】2005-2019年我国272个地级市的旅游竞争力多指标数据(33个指标)
旅游业是一个城市的重要产业构成。旅游竞争力是一个城市竞争力的重要构成部分。一个城市的旅游竞争力反映了其在旅游市场竞争中的比较优势。 今日我们分享的是2005-2019年我国272个地级市的旅游竞争力多指标数据!该数据集源自2025年4月发表于《地理学报》的论文成果…...
Python学习(8) ----- Python的类与对象
Python 中的类(Class)与对象(Object)是面向对象编程(OOP)的核心。我们可以通过“类是模板,对象是实例”来理解它们的关系。 🧱 一句话理解: 类就像“图纸”,对…...
结构化文件管理实战:实现目录自动创建与归类
手动操作容易因疲劳或疏忽导致命名错误、路径混乱等问题,进而引发后续程序异常。使用工具进行标准化操作,能有效降低出错概率。 需要快速整理大量文件的技术用户而言,这款工具提供了一种轻便高效的解决方案。程序体积仅有 156KB,…...
02-性能方案设计
需求分析与测试设计 根据具体的性能测试需求,确定测试类型,以及压测的模块(web/mysql/redis/系统整体)前期要与相关人员充分沟通,初步确定压测方案及具体的性能指标QA完成性能测试设计后,需产出测试方案文档发送邮件到项目组&…...
