提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
- 3.1线程概述
- 3.2 创建线程
- 3.3、线程终止
- 3.4连接已经终止线程
- 3.5 线程的分离
- 3.6 线程取消
- 3.7 线程属性
- 3.8 线程同步
- 3.9 互斥锁
- 3.10 死锁
- 3.11 读写锁
- 3.12 生产者和消费者模型
- 3.13 条件变量
- 3.14 信号量
3.1线程概述
◼ 与进程(process)类似,线程(thread)是允许应用程序并发执行多个任务的一种机制。一个进程可以包含多个线程。同一个程序中的所有线程均会独立执行相同程序,且共享同一份全局内存区域,其中包括初始化数据段、未初始化数据段,以及堆内存段。(传统意义上的 UNIX 进程只是多线程程序的一个特例,该进程只包含一个线程)
◼ 进程是 CPU 分配资源的最小单位,线程是操作系统调度执行的最小单位。
◼ 线程是轻量级的进程(LWP:Light Weight Process),在 Linux 环境下线程的本质仍是进程。
◼ 查看指定进程的 LWP 号:ps –Lf pid
提示:
◼ 进程间的信息难以共享。由于除去只读代码段外,父子进程并未共享内存,因此必须采用
一些进程间通信方式,在进程间进行信息交换。
◼ 调用 fork() 来创建进程的代价相对较高,即便利用写时复制技术,仍然需要复制诸如
内存页表和文件描述符表之类的多种进程属性,这意味着 fork() 调用在时间上的开销
依然不菲。
◼ 线程之间能够方便、快速地共享信息。只需将数据复制到共享(全局或堆)变量中即可。
◼ 创建线程比创建进程通常要快 10 倍甚至更多。线程间是共享虚拟地址空间的,无需采
用写时复制来复制内存,也无需复制页表。
◼ 共享资源
进程 ID 和父进程 ID
进程组 ID 和会话 ID
用户 ID 和 用户组 ID
文件描述符表
信号处置
文件系统的相关信息:文件权限掩码
(umask)、当前工作目录
虚拟地址空间(除栈、.text)
◼ 非共享资源
线程 ID
信号掩码
线程特有数据
error 变量
实时调度策略和优先级
栈,本地变量和函数的调用链接信息
提示:以下是本篇文章正文内容,下面案例可供参考
3.2 创建线程
进程:计算机分配资源的最小单位
线程:计算机调度的最小单位
gcc pthread_exit.c -o exit -pthread //第三方库pthread
/*
#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
-功能:创建一个子线程;一般情况,main函数所在的线程称为主线程(main线程)
其余创建的线程称为子线程
程序中默认只有一个进程,fork()函数调用,2个进程
程序中默认只有一个线程
-参数:
thread:传出参数,创建成功的子线程的ID
attr:设置线程的属性,一般默认值,NULL
start_routine:函数指针,子线程需要处理的逻辑代码
arg:给第三个参数使用,传参数
返回值:
成功:0
失败:返回错误号,这个错误号和之前errno不一样
获取错误号信息:char* strerror(int errnum) ;
*/
#include<stdio.h>
#include<pthread.h>
#include<string.h>
#include<unistd.h>
void *callback(void *arg){
printf("childthread\n");
printf("arg value:%d\n",*(int *)arg);
return NULL;
}
int main(){
pthread_t tid;
int num =99;
//创建一个子线程
int ret=pthread_create(&tid,NULL,callback,(void*)&num);
if(ret!=0){
char *errstr = strerror(ret);
printf("error:%s\n",errstr);
}
for(int j = 0; j < 10; j++) {
printf("j = %d\n", j);
sleep(1);
}
return 0; // exit(0);
}
3.3、线程终止
/*
#include <pthread.h>
void pthread_exit(void *retval);
功能:终止一个线程,在哪个线程中调用,就表示终止哪个线程
参数:
retval:需要传递一个指针,作为一个返回值,可以在pthread_join()中获取
pthread_t pthread_self(void);
获取当前线程的线程ID
int pthread_equal(pthread_t t1, pthread_t t2); // 跨平台使用
比较两个线程ID是否相等
不同的操作系统,pthread_t的类型不一样,
有无符号long int, 也有结构体
*/
#include<stdio.h>
#include<pthread.h>
#include<string.h>
void *callback(void *arg){
printf("childthread ID :%ld\n",pthread_self());
return NULL;//pthread_exit(NULL);
}
int main(){
pthread_t tid;
//创建一个子线程
int ret=pthread_create(&tid,NULL,callback,NULL);
if(ret!=0){
char *errstr = strerror(ret);
printf("error:%s\n",errstr);
}
for(int j = 0; j < 1000; j++) {
printf("j = %d\n", j);
}
printf("tid:%ld, mainthread ID :%ld\n",tid,pthread_self());
//退出主线程,但是不会影响其他子线程的运行
pthread_exit(NULL);
printf("living?\n");//无法执行
return 0;//exit(0);
}
3.4连接已经终止线程
/*
#include <pthread.h>
int pthread_join(pthread_t thread, void **retval);
和已经终止的线程连接进行连接
回收子线程的资源
这个函数是阻塞函数,调用一次只能回收一个子线程
一般在主线程中使用
thread:需要回收的子线程的ID
retval:接受子线程退出时的返回值
返回值:
0:成功
非0 :失败,返回错误号
*/
#include<stdio.h>
#include<pthread.h>
#include<string.h>
#include<unistd.h>
int value=10;
void *callback(void *arg){
printf("childthread ID :%ld\n",pthread_self());
sleep(3);
//return NULL;//pthread_exit(NULL);
//int value= 10; 不能返回局部变量,线程结束,栈空间释放,返回随机值
pthread_exit((void *)&value);//return (void *)&value;
}
int main(){
pthread_t tid;
//创建一个子线程
int ret=pthread_create(&tid,NULL,callback,NULL);
if(ret!=0){
char *errstr = strerror(ret);
printf("error:%s\n",errstr);
}
for(int j = 0; j < 10; j++) {
printf("j = %d\n", j);
}
printf("tid:%ld, mainthread ID :%ld\n",tid,pthread_self());
//主线程调用pthread_join()回收子线程资源
int *thread_retval;
int re=pthread_join(tid,(void **)&thread_retval);
//为什么传递二级指针,
//对int变量的值操作时,要传入一级指针
//而对int *进行操作,传入二级指针
if(re!=0){
char *errstr = strerror(ret);
printf("error:%s\n",errstr);
}
printf("exit data:%d\n",*thread_retval);
printf("回收子线程成功!\n");
//退出主线程,但是不会影响其他子线程的运行
pthread_exit(NULL);
return 0;
}
3.5 线程的分离
/*
#include <pthread.h>
int pthread_detach(pthread_t thread);
分离一个线程,被分离的线程在终止时,会自动释放资源返回系统
1.不能多次分离,会产生不可预料的行为
2.不能去连接一个已经分离的线程,会报错
thread:需要分离的线程ID
返回值:
成功0;
失败:返回错误号
*/
#include <pthread.h>
#include<stdio.h>
#include<string.h>
#inclu
标签:printf,include,int,void,Linux,C++,线程,pthread,多线程
From: https://blog.csdn.net/love_boke/article/details/136553947