分类网站上怎么做锚文本,做er图的网站,婚纱摄影网站模板,网站建设信(信科网络)目录 一、基本知识点二、线程的编译三、 线程相关函数1. 线程的创建#xff08;1#xff09;整型的传入与接收#xff08;2#xff09;浮点数的传入与接收#xff08;3#xff09;字符串的传入与接收#xff08;4#xff09;结构体的传入与接收 2. 线程的退出3. 线程的… 目录 一、基本知识点二、线程的编译三、 线程相关函数1. 线程的创建1整型的传入与接收2浮点数的传入与接收3字符串的传入与接收4结构体的传入与接收 2. 线程的退出3. 线程的等待补充1返回整型2返回浮点数3返回字符串4返回结构体 四、综合举例 一、基本知识点 定义 线程Thread是操作系统能够进行运算调度的最小单位。它被包含在进程之中是进程中的实际运作单位。每一个进程都至少包含一个main线程。 相比于进程而言线程更加轻量级因为它们共享了进程的地址空间以及其他资源所以线程之间的切换和通信会更加高效。一个进程可以包含多个线程这些线程可以并发执行各自独立完成一些特定的任务或者共同完成一个复杂的任务。进程里每个线程执行的顺序不一定。主线程结束则所有线程结束。 共享资源保护 由于某一线程与同属一个进程的其他的线程共享进程的资源如内存空间、文件描述符和其他一些进程相关的属性。所以在多线程编程中通常会涉及到共享资源保护操作如互斥锁等以确保线程之间的协调运行避免资源竞争和数据不一致的问题。即每次对共享资源进行操作时只能有一个线程操作其他线程必须等待操作完毕后才能对其继续操作。
二、线程的编译 Linux 的线程是通过用户级的函数库实现的一般采用 pthread 线程库实现线程的访问和控制。它用第 3 方 posix 标准的 pthread具有良好的可移植性。在使用了线程的代码编译的时候要在后面加上 -lpthread。
例如gcc test.c -o test -lpthread
三、 线程相关函数
头文件#include pthread.h 1. 线程的创建
int pthread_create(pthread_t* thread, pthread_attr_t * attr, void *(*start_routine)(void *), void * arg);
//pthread_t* thread 线程的句柄用于区分是哪个线程。
//pthread_attr_t * attr 线程的属性通常为NULL。
//void *(*start_routine)(void *) 线程所执行的函数该函数形参和返回值都要为void *。
// void * arg 该值用于传递第三个参数函数的形参如果不传递可以为NULL。举例
1整型的传入与接收
#include sys/types.h
#include stdio.h
#include string.h
#include unistd.h
#include pthread.h
void *task(void *arg)
{int *num(int *)arg;while(1){sleep(1); printf(我是子线程,传入参数为%d\n,*num);}
}int main()
{int num 100;pthread_t thread; //定义线程句柄pthread_create(thread, NULL, task, (void *)num); //创建线程并绑定线程函数。 while(1){sleep(1); printf(我是主线程\n);}
}2浮点数的传入与接收
#include sys/types.h
#include stdio.h
#include string.h
#include unistd.h
#include pthread.h
void *task(void *arg)
{float*num(float *)arg;while(1){sleep(1); printf(我是子线程,传入参数为%f\n,*num);}
}int main()
{float num 10.10;pthread_t thread; //定义线程句柄pthread_create(thread, NULL, task, (void *)num); //创建线程并绑定线程函数。 while(1){sleep(1); printf(我是主线程\n);}
}3字符串的传入与接收
#include sys/types.h
#include stdio.h
#include string.h
#include unistd.h
#include pthread.h
void *task(void *arg)
{char *num(char *)arg;while(1){sleep(1); printf(我是子线程,传入参数为%s\n, num);}
}int main()
{char *stringi love you;pthread_t thread; //定义线程句柄pthread_create(thread, NULL, task, (void *)string); //创建线程并绑定线程函数。 while(1){sleep(1); printf(我是主线程\n);}
}4结构体的传入与接收
#include sys/types.h
#include stdio.h
#include string.h
#include unistd.h
#include pthread.hstruct people{char *name;int age;
};void *task(void *arg)
{struct people *student(struct people*)arg;while(1){sleep(1); printf(我是子线程,传入参数名字%s年龄:%d\n, student-name,student-age);}
}int main()
{struct people *student;pthread_t thread; //定义线程句柄//将结构体赋值student-age10;strcpy(student-name, John); pthread_create(thread, NULL, task, (void *)student); //创建线程并绑定线程函数。 while(1){sleep(1); printf(我是主线程\n);}
}2. 线程的退出 函数 pthread_exit 表示线程的退出。其传入的的参数可以被其它线程用 pthread_join 等待函数进行捕获。例如 pthread_exit( (void*)3 ); 表示线程退出并将 3作为返回值被后面的 pthread_join 函数捕获。该函数的作用就是可以将该线程的计算结果传递给创建它的主线程或者其他线程。 注意1在使用线程函数时不能随意使用 exit 退出函数进行出错处理由于 exit 的作用是使调用进程终止往往一个进程包括了多个线程所以在线程中通常使用 pthread_exit 函数来代替进程中的退出函数 exit。 注意2如果线程退出的返回值是在线程内部定义的局部变量的话记得加static修饰增加变量的生命周期直至进程结束而结束。不然线程退出后该片内存地址会立刻被销毁此时返回的空间无效。或者将返回值修改为全局变量。
void pthread_exit(void *retval);
//void *retval作为线程退出时的值。如果不需要捕获该值可以传入NULL。3. 线程的等待 当父线程结束的时候如果没有 pthread_join 函数等待子线程执行的话父线程会退出而主线程的退出会导致进程的退出故子线程也会退出。 由于一个进程中的多个线程是共享数据段的因此通常在线程退出之后退出线程所占用的资源并不会随着线程的终止而得到释放。正如进程之间可以通过 wait()函数系统调用来同步终止并释放资源一样线程之间也有类似的机制那就是 pthread_join 函数。这个函数是一个线程阻塞函数调用这函数的线程将一直等待直到被等待的线程结束为止当函数返回时被等待线程的资源被回收。
int pthread_join(pthread_t pthid, void **thread_return);
//pthread_t pthid 线程句柄。
//void **thread_return 用于接收线程退出的返回值。如果没有需要接收的填NULL。上述函数第二个参数为二级指针所以我们可以定义一级指针再取地址来获取该值然后再进行强制类型转换为(void **)。
举例 思考上述例程中为什么要用static来修饰变量呢 答这是因为当线程退出时其在内部定义的变量都会被销毁可以将变量设为全局变量或者使用static来修饰变量增加其生命周期直至进程结束才会被销毁。不然返回的地址将是一个已经被销毁的地址无法使用。
补充 一般线程的退出和线程的等待是一起使用的。这里我们使用几种参数类型进行举例。
1返回整型
//退出
static int a10;
pthread_exit((void *) a);
//-------------------------------//等待接收
int *thread_result;
pthread_join(thread,(void **)thread_result);
printf(子线程的返回值为%d\n, *thread_result);2返回浮点数
//退出
static float f10.12;
pthread_exit((void *) f);
//-------------------------------
//等待接收
float *thread_result;
pthread_join(thread,(void **)thread_result);
printf(子线程的返回值为%f\n, *thread_result);3返回字符串
//退出
static char *stringi love you!;
pthread_exit((void *)string);
//-------------------------------
//等待接收
char *thread_result;
pthread_join(thread,(void **)thread_result);
printf(子线程的返回值为%s\n, thread_result);4返回结构体
typedef struct
{char *name; //定义指针后续使用时要为其开辟内存空间 如果不想开辟空间则使用数组。int age;
}people;//退出people *student (people *)malloc(sizeof(people)); //给结构体开辟空间然后赋值。student-name(char *)malloc(sizeof(char *)); //为结构体里定义的字符指针开辟内存空间。//给结构体赋值strcpy(student-name,john);student-age12;pthread_exit((void *)student);//等待接收student *thread_result;pthread_join(thread,(void **)thread_result);printf(名字为%s,年龄为%d\n, thread_result-name,thread_result-age);四、综合举例
#include sys/types.h
#include stdio.h
#include string.h
#include unistd.h
#include pthread.hvoid *task1(void * arg) //线程1函数
{float *num (float *)arg;while(1){sleep(1);printf(这是子线程1传入的值为%f\n,*num);}
}void *task2(void * arg) //线程2函数
{int *num (int *)arg;static char *stringpthread2_end;while(1){ sleep(1);printf(这是子线程2传入的值为%d\n,*num);(*num)--;if(*num 0) break;}pthread_exit((void *)string);
}int main()
{float pthread1_arg11.2; //传入线程函数1的参数int pthread2_arg3; //传入线程函数2的参数char *string;int ret;pthread_t thread1,thread2;//线程句柄//创建线程1retpthread_create(thread1, NULL, task1, (void *) pthread1_arg);if(ret0) {perror(pthread1_create error!\n);return -1;}//创建线程2retpthread_create(thread2, NULL, task2, (void *) pthread2_arg);if(ret0) {perror(pthread2_create error!\n);return -1;}pthread_join(thread2, (void **)string);printf(%s\n,string);return 0;
}