什么是线程?
“线程”有时候被称为轻量级进程,是程序执行流的最小单元,一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成。另外,线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。由于线程之间的相互制约,致使线程在运行中呈现出间断性。每一个程序都至少有一个线程,那就是程序本身。线程是程序中一个单一的顺序控制流程。 在单个程序中同时运行多个线程完成不同的工作,称为多线程。(同一进程的多个线程共享同一地址空)
线程的特点:
一,线程的私有:
1,私有栈结构。
2,线程都是具有上下文信息的。
二,独立调度和分配的基本单位
在多线程OS中,线程是能独立运行的基本单位,因而也是独立调度和分派的基本单位。由于线程很“轻”,故线程的切换非常迅速且开销小(在同一进程中的)。
三,可并发执行。
在一个进程的多个线程之间,可以并发执行,甚至允许在一个进程中的所有线程都能同时执行;同样,不同进程中的线程也能并发执行。
四,共享进程资源。
在同一进程中的各个线程,都可以共享该进程所拥有的资源,这首先表现在:所有线程都具有相同的地址空间(进程的地址空间),这意味着,线程可以访问该地址空间的每一个虚地址;此外,还可以访问进程所拥有的已打开文件、定时器、信号量机构等。由于同一个进程内的线程共享内存和文件,所以线程之间互相通信不必调用内核.
线程的属性:
1,可分离
2,可结合(默认属性)
一个可结合的线程能够被其他线程收回其资源和杀死。在被其他线程回收之前,它的存储器资源(例如栈)是不释放的。相反,⼀个分离的线程是不能被其他线程回收或杀死的,它的存储器 资源在它终⽌止时由系统自动释放。
pthread_detach(thread_id);//(非阻塞,可立即返回)。这将该子线程的状态设置为分离的(detached),如此⼀来,该线程运行结束后会自动释放所有资源
分离自己:直接pthread_detach(pthread_self());
线程与进程的区别可以归纳为以下4点:
1)地址空间和其它资源(如打开文件):进程间相互独立,同一进程的各线程间共享。某进程内的线程在其它进程不可见。
2)通信:进程间通信IPC,线程间可以直接读写进程数据段(如全局变量)来进行通信——需要进程同步和互斥手段的辅助,以保证数据的一致性。
3)调度和切换:线程上下文切换比进程上下文切换要快得多。
4)在多线程OS中,进程不是一个可执行的实体。
创建一个线程:
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
void *thread_run(void *arg)
{
printf("new thread,thread is :%u,pid is:%d\n",pthread_self(),getpaid());
return (void *)1;
}
int main()
{
pthread_tid;
pthread_create(&tid,NULL,thread_run,NULL);//创建线程函数
printf("main thread,thread is:%u,pid is:%d\n",pthread_self(),getpid());
return 0;
}
运行结果:
注意:编译时要加上 -lpthread。每个线程都有自己的线程ID,以便在进程内区分。线程ID在pthread_create调用时回返给创建线程的调用者;一个线程也可以在创建后使用pthread_self()调用获取自己的线程ID:
线程等待:
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
void *thread_run(void *arg)
{
printf("new thread,thread is :%u,pid is:%d\n",pthread_self(),getpaid());
return (void *)1;
}
int main()
{
pthread_tid;
pthread_create(&tid,NULL,thread_run,NULL);//创建线程函数
void *ret;
pthread_join(tid,&ret);//线程等待函数
printf("join new success,ret:%d\n",(int)ret);
return 0;
}
运行结果:
线程等待函数:
int pthread_join(pthread_t thread,void **retval);
调用该函数的线程将挂起等待,直到id为thread的线程终⽌止。thread线程以不同的方法终止,通过pthread_join得到的终⽌止状态是不同的,总结如下:
1. 如果thread线程通过return返回,value_ptr所指向的单元⾥里存放的是thread线程函数的返回值。
2. 如果thread线程被别的线程调用pthread_cancel异常终掉,value_ptr所指向的单元里存放的是常数PTHREAD_CANCELED。
3. 如果thread线程是⾃⼰调用pthread_exit终止的,value_ptr所指向的单元存放的是传给pthread_exit的参数。 如果对thread线程的终⽌止状态不感兴趣,可以传NULL给value_ptr参数。
终止线程而不终止进程的方法:
1,在线程中return;(不适用主线程,若在主线程退出,则进程退出)
2,调用pthread_exit(void * retval)函数。(自己终止自己)
3,调用pthread_cancel()函数。(此函数比较复杂)。