线程是进程内部的一条执行序列(执行流),一个进程至少有一个线程,main函数所代表的执行流。通过线程库创建新的线程,称之为函数线程。同一个进程的线程是并发执行的。
实现方式
1.用户级线程(用户管控线程)
缺点:内核只通过进程PCB管控进程,故无法管控线程,导致线程的实现只能由用户来完成。
当线程阻塞时,内核也无法调控,所以实现复杂度很高
优点:调控线程不用陷入内核执行
2.内核级线程(内核管控线程)
优点:取消了用户对线程的管控
缺点:陷入内核的操作用去了大量的时间(线程的创建,销毁等操作由内核调控)
3.混合级线程(内核与用户一起管控,管控线程可能不等)
Linux上线程库的使用
1.怎么创建一个线程:
int pthread create(pthread_t *id,pthread_attr_t *attr,void *(*pthread_fun)(void *)fun,void *arg)
(void *(*pthread_fun)(void *) fun)指定新创建的线程的执行流开始位置
(void *arg)传递给函数的参数
2.怎么结束一个线程
int pthread_exit(void *val);
3.怎么阻塞一个线程
int pthread_join(pthread_t id,void **reval);
阻塞,直到等待的线程的结束;等待一个线程结束,reval获取pthread_exit函数返回的指针
4.怎么终止一个线程
int pthread_cancel(pthread_t id); 终止一个线程
进程与线程的区别
1.进程是资源分配的单位,线程是CPU调度的单位
2.线程的切换效率比进程的切换高
——因为线程所占的内存比进程少得多,所以线程的切换效率比进程高得多
3.同一个线程之间共享数据空间&文件描述符
线程共享
线程共享:线程共享资源空间和文件描述符
下面我展示线程共享资源空间的代码(其中资源空间包括.data, .bss,堆区空间)
1.线程共享.data区的资源
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<unistd.h>
#include<fcntl.h>
#include<pthread.h>
void *fun(void *arg)
{
int *j=(int *)arg;
int i=0;
for(;i<5;i++)
{
*j=1;
printf("fun:pid=%d,fun thread running\n",getpid());
sleep(1);
}
pthread_exit(NULL);
}
int main()
{
pthread_t id;
int j=10;
int i=0;
printf("%d\n",j);
for(;i<3;i++)
{
int ret=pthread_create(&id,NULL,fun,(void *)&j);
assert(ret==0);
}
i=0;
for(;i<3;i++)
{
printf("main:pid=%d,main thread running\n",getpid());
sleep(1);
}
printf("%d\n",j);
pthread_exit(NULL);
}
2.线程共享.bss区的资源
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<unistd.h>
#include<fcntl.h>
#include<pthread.h>
void *fun(void *arg)
{
int i=0;
int *p=(int *)arg;
for(;i<5;i++)
{
*p=10;
printf("fun:pid=%d,fun thread running\n",getpid());
sleep(1);
}
pthread_exit(NULL);
}
int main()
{
int p;
pthread_t id;
int i=0;
printf("%d\n",p);
for(;i<3;i++)
{
int ret=pthread_create(&id,NULL,fun,(void *)&p);
assert(ret==0);
}
i=0;
for(;i<3;i++)
{
printf("main:pid=%d,main thread running\n",getpid());
sleep(1);
}
printf("%d\n",p);
pthread_exit(NULL);
}
3.线程共享堆区空间
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<unistd.h>
#include<fcntl.h>
#include<pthread.h>
void *fun(void *arg)
{
int *p=(int *)arg;
int i=0;
int j=10;
for(;i<5;i++)
{
*p=10;
printf("fun:pid=%d,fun thread running\n",getpid());
}
pthread_exit(NULL);
}
int main()
{
pthread_t id;
int *p=(int *)malloc(sizeof(int));
*p=1;
printf("%d\n",*p);
int i=0;
for(;i<3;i++)
{
int ret=pthread_create(&id,NULL,fun, (void *)p);
assert(ret==0);
}
i=0;
for(;i<3;i++)
{
printf("main:pid=%d,main thread running\n",getpid());
sleep(1);
}
printf("%d\n",*p);
pthread_exit(NULL);
}
下面我在展示线程共享文件描述符的代码
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<unistd.h>
#include<fcntl.h>
#include<pthread.h>
#include<string.h>
void *fun(void *arg)
{
int b=(int)arg;
char buff[128]={0};
int i=0;
for(;i<5;i++)
{
printf("fun:pid=%d,fun thread running\n",getpid());
write(b,"Happy",5);
//sleep(1);
}
pthread_exit(NULL);
}
int main()
{
int fd=open("a.txt",O_CREAT | O_TRUNC | O_RDWR,0666);
char buff[128]={"Hello world."};
char buff1[128]={0};
write(fd,buff,strlen(buff));
pthread_t id;
int i=0;
for(;i<3;i++)
{
int ret=pthread_create(&id,NULL,fun,(void *)fd);
assert(ret==0);
}
i=0;
for(;i<3;i++)
{
printf("main:pid=%d,main thread running\n",getpid());
//sleep(1);
}
read(fd,buff1,127);
printf("%s\n",buff1);
fflush(stdout);
pthread_exit(NULL);
}
根据以上代码,我们发现线程在资源空间和文件描述符都是共享的。