目录
概述
程序
进程
线程
区别
特点
线程共享资源
线程非共享资源
线程的优缺点
线程号
线程号
查看是否有线程函数列表
命令
安装
获取线程号pthread_self函数
可执行文件
操作系统分配资源的最小单位
CPU调度的最小单位
所以,线程是轻量级的进程(LWP:light weightprocess),在Linux环境下线程的本质仍是进程。为了让进程完成一定的工作,进程必须至少包含一个线程。
1)文件描述符表
2) 每种信号的处理方式
3) 当前工作目录
4) 用户ID和组ID 内存地址空间
(.text/.data/.bss/heap/共享库)
1) 线程id
2) 处理器现场和栈指针(内核栈)
3) 独立的栈空间(用户空间栈)
4) errno变量
5) 信号屏蔽字
6)调度优先级
优点: Ø 提高程序并发性 Ø 开销小 Ø 数据通信、共享数据方便
缺点: Ø 库函数,不稳定 Ø 调试、编写困难、gdb不支持 Ø 对信号支持不好 优点相对突出,缺点均不是硬伤。Linux下由于实现方法导致进程、线程差别不是很大。
就像每个进程都有一个进程号一样,每个线程也有一个线程号。进程号在整个系统中是唯一的,但线程号不同,线程号只在它所属的进程环境中有效。 进程号用 pid_t 数据类型表示,是一个非负整数。线程号则用 pthread_t 数据类型来表示,Linux 使用无符号长整数表示。 有的系统在实现pthread_t 的时候,用一个结构体来表示,所以在可移植的操作系统实现不能把它做为整数处理
man -k pthread
如果出现一堆东西说明可用如果没有就进行安装
sudo apt-get install manpages-posix-dev
就像每个进程都有一个进程号一样,每个线程也有一个线程号。进程号在整个系统中是唯一的,但线程号不同,线程号只在它所属的进程环境中有效。 进程号用 pid_t 数据类型表示,是一个非负整数。线程号则用 pthread_t 数据类型来表示,Linux 使用无符号长整数表示。 有的系统在实现pthread_t 的时候,用一个结构体来表示,所以在可移植的操作系统实现不能把它做为整数处理
#include
pthread_t pthread_self(void);
功能:
获取线程号。
参数:
无
返回值:
调用线程的线程 ID
#include
#include
int main()
{
pthread_t tid = pthread_self();
printf(" %ld\n", tid);
return 0;
}
注意:进行编译时需要链接库,直接用make进行编译会出现一下情况
#include
int pthread_create(pthread_t *thread,
const pthread_attr_t *attr,
void *(*start_routine)(void *),
void *arg );
功能:
创建一个线程
参数:
thread:线程标识符地址。
attr:线程属性结构体地址,通常设置为 NULL。
start_routine:线程函数的入口地址。
arg:传给线程函数的参数。
返回值:
成功:0
失败:非 0
#include
#include
#include
void *fun(void *arg)
{
pthread_t tid;
while(1)
{
tid = pthread_self();
printf("新创建的线程 = %ld\n", tid);
sleep(1);
}
}
int main()
{
pthread_t tid, tid1;
pthread_create(&tid1, NULL, fun, NULL);
while(1)
{
pthread_t tid = pthread_self();
printf("进程自带线程: %ld\n", tid);
sleep(1);
}
return 0;
}
定义一个局部变量,在其中一个线程中执行++操作,在另一个线程中进行printf输出,可发现输出的变量在执行++操作
将值作为形参传入函数,但需要进行类型转换
将值的地址作为参数传入函数,对其处理时也需要进行类型转换
#include
#include
#include
//int num=0;
#if 0
//值传递
void *fun1(void *arg)
{
int num=(int)arg;
while(1)
{
printf("fun1 = %d\n", num);
sleep(1);
}
}
void *fun2(void *arg)
{
int num=(int)arg;
while(1)
{
num++;
printf("fun2 = %d\n", num);
sleep(1);
}
}
int main()
{
int num=0;
pthread_t tid,tid1,tid2;
pthread_create(&tid1,NULL,fun1,(void *)num);
pthread_create(&tid2,NULL,fun2,(void *)num);
while(1);
return 0;
}
#endif
//地址传递
void *fun1(void *arg)
{
while(1)
{
printf("fun1 = %d\n", *(int*)arg);
sleep(1);
}
}
void *fun2(void *arg)
{
while(1)
{
(*(int*)arg)++;
printf("fun2 = %d ************\n",*(int*)arg);
sleep(1);
}
}
int main()
{
int num=0;
pthread_t tid,tid1,tid2;
pthread_create(&tid2,NULL,fun2,(void *)&num);
pthread_create(&tid1,NULL,fun1,(void *)&num);
while(1);
return 0;
}
#include
int pthread_join(pthread_t thread, void **retval);
功能:
等待线程结束(此函数会阻塞),并回收线程资源,类似进程的 wait() 函数。如果线程已经结束,那么该函数会立即返回。
参数:
thread:被等待的线程号。
retval:用来存储线程退出状态的指针的地址
返回值:
成功:0
失败:非 0
#include
#include
#include
#include
int num =0;
void *pthid1_callback(void *agr)
{
int a=0;
for(int i=0;i<5;i++)
{
num++;
printf("i am pth 1 run\n");
sleep(1);
}
}
void *pthid2_callback(void *agr)
{
for(int i=0;i<2;i++)
{
printf("i am pth 2 run num=%d\n",num);
sleep(1);
}
}
int main(int argc, char *argv[])
{
pthread_t pthid1,pthid2;
//创建线程
pthread_create(&pthid1,NULL,pthid1_callback,NULL);
pthread_create(&pthid2,NULL,pthid2_callback,NULL);
pthread_join(pthid1,NULL);//等5s 阻塞
pthread_join(pthid2,NULL);
return 0;
}
#include
int pthread_detach(pthread_t thread);
功能:
使调用线程与当前进程分离,分离后不代表此线程不依赖与当前进程,线程分离的目的是将线程资源的回收工作交由系统自动来完成,也就是说当被分离的线程结束之后,系统会自动回收它的资源。所以,此函数不会阻塞
参数:
thread:线程号。
返回值:
成功:0
失败:非0
#include
void pthread_exit(void *retval);
功能:
退出调用线程。一个进程中的多个线程是共享该进程的数据段,因此,通常线程退出后所占用的资源并不会释放。
参数:
retval:存储线程退出状态的指针。
返回值:无
#include
#include
#include
void *callback(void *arg)
{
int i=0;
while(1)
{
printf("hello world\n");
sleep(1);
if(50 == i++)
pthread_exit(NULL);
}
return NULL;
}
int main(int argc, char *argv[])
{
pthread_t pthid;
pthread_create(&pthid,NULL,callback,NULL);
printf("join\n");
pthread_join(pthid,NULL);
printf("join ok\n");
return 0;
}
#include
int pthread_cancel(pthread_t thread);
功能:
杀死(取消)线程
参数:
thread : 目标线程ID。
返回值:
成功:0
失败:出错编号
void *thread_cancel(void *arg)
{
while (1)
{
pthread_testcancel(); //设置取消点
}
return NULL;
}
int main()
{
pthread_t tid;
pthread_create(&tid, NULL, thread_cancel, NULL); //创建线程
sleep(3); //3秒后
pthread_cancel(tid); //取消tid线程
pthread_join(tid, NULL);
return 0;
}