线程:
线程是轻量级的进程。
进程:拥有独立的地址空间,拥有PCB,相当于独居
线程:有PCB,但没有独立的地址空间,多个线程共享进程空间,相当于合租
进程可以蜕变为线程
ps -Lf 进程id -->可以查看此进程的线程
线程共享资源:
- 文件描述符表
- 每种信号的处理方式
- 当前工作目录
- 用户ID和组ID
- 内存地址空间
线程非共享资源:
- 线程id
- 栈
- errno变量
- 信号屏蔽字
- 调度优先级
特点:
- 系统分配资源的基本单位是:进程
- 系统调度进程执行的最小单位是:线程
- 多个子线程和主线程共享一个地址空间,只有一个相同的PID
- 通过使用线程号来区分不同的线程
- 除了栈空间的资源,其余资源都可以共享
- 主线程和子线程谁先抢到cpu时间片谁先执行
pthread_create函数
函数原型:int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
返回值:
- 成功返回0;
- 失败返回错误号;
函数参数:
- pthread_:传出参数,保存线程id
- attr:通常设为NULL
- star_routine:函数指针
- arg:线程主函数执行期间所使用的参数
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<unistd.h>
#include <pthread.h>
void *mythread(void*arg)//子线程执行函数
{
printf("child thread,pid==[%d],id==[%ld]\n",getpid(),pthread_self());
}
int main()
{
//int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
// void *(*start_routine) (void *), void *arg);
pthread_t thread;
int ret=pthread_create(&thread,NULL,mythread,NULL);
if(ret!=0)
{
printf("pthread_create error:[%s]\n",strerror(ret));
return -1;
}
printf("father thread,pid==[%d],id==[%ld]\n",getpid(),pthread_self());
sleep(1);防止主线程已经结束,进程退出,而子线程还没有执行
}
结果:
传递参数的使用:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<unistd.h>
#include <pthread.h>
void *mythread(void*arg)
{
int *n=(int *)arg;//强转类型
printf("[%d]\n",*n);
printf("child thread,pid==[%d],id==[%ld]\n",getpid(),pthread_self());
}
int main()
{
//int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
// void *(*start_routine) (void *), void *arg);
int n=9;
pthread_t thread;
int ret=pthread_create(&thread,NULL,mythread,&n);
if(ret!=0)
{
printf("pthread_create error:[%s]\n",strerror(ret));
return -1;
}
printf("father thread,pid==[%d],id==[%ld]\n",getpid(),pthread_self());
sleep(1);
}
循环创建五个子线程,并让每个子线程知道自己是第几个线程
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<unistd.h>
#include <pthread.h>
void *mythread(void*arg)
{
int i=*(int *)arg;//强转类型
printf("[%d]child thread,pid==[%d],id==[%ld]\n",i,getpid(),pthread_self());
}
int main()
{
//int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
int i=0; // void *(*start_routine) (void *), void *arg);
pthread_t thread[5];
for(i=0;i<5;i++)
{
int ret=pthread_create(&thread[i],NULL,mythread,&i);
if(ret!=0)
{
printf("pthread_create error:[%s]\n",strerror(ret));
return -1;
}
}
// printf("father thread,pid==[%d],id==[%ld]\n",getpid(),pthread_self());
sleep(1);
}
这样子每个子线程都是打印出第5个。
原因:由于i的内存空间只有一块,这块空间由五个子线程共享,而主线程在一个cpu时间片内就可以把五个子线程创建出来,退出循环此时i==5,所以都打印出5.。
解决方法一:每创建一个子线程,sleep(1)一下,让当前此子线程直接获得cpu时间片
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<unistd.h>
#include <pthread.h>
void *mythread(void*arg)
{
int i=*(int *)arg;//强转类型
printf("[%d]child thread,pid==[%d],id==[%ld]\n",i,getpid(),pthread_self());
}
int main()
{
//int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
int i=0; // void *(*start_routine) (void *), void *arg);
pthread_t thread[5];
for(i=0;i<5;i++)
{
int ret=pthread_create(&thread[i],NULL,mythread,&i);
if(ret!=0)
{
printf("pthread_create error:[%s]\n",strerror(ret));
return -1;
}
sleep(1);
}
// printf("father thread,pid==[%d],id==[%ld]\n",getpid(),pthread_self());
sleep(1);
}
解决方法二:创建数组存放不同的i值,让每个子线程不是共享同一个空间,这样一来子线程的顺序就会变了,谁先获得cpu时间片谁先执行。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<unistd.h>
#include <pthread.h>
void *mythread(void*arg)
{
int i=*(int *)arg;//强转类型
printf("[%d]child thread,pid==[%d],id==[%ld]\n",i,getpid(),pthread_self());
}
int main()
{
//int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
int i=0; // void *(*start_routine) (void *), void *arg);
int arr[5];
pthread_t thread[5];
for(i=0;i<5;i++)
{
arr[i]=i;
int ret=pthread_create(&thread[i],NULL,mythread,&arr[i]);
if(ret!=0)
{
printf("pthread_create error:[%s]\n",strerror(ret));
return -1;
}
}
// printf("father thread,pid==[%d],id==[%ld]\n",getpid(),pthread_self());
sleep(1);
}
这里子线程共享了栈里的内容,因为这是在主线程里创建的栈,等到主线程结束时才会释放,所以不同子线程可以共享主线程创建的栈(主线程没结束),不同子线程创建的栈不可以共享。