一. 概念
首先Linux并不存在真正的线程,Linux的线程是使用进程模拟的。当我们需要在一个进程中同时运行多个执行流时,我们并不可以开辟多个进程执行我们的操作(32位机器里每个进程认为它 独享 4G的内存资源),此时便引入了线程,例如当我们既需要下载内容,又需要浏览网页时,此时多线程便起了作用。线程是承担调度的基本单位,一个进程可拥有多个线程,它的执行力度比进程更加细致,线程资源共享。
二. 特点
由于同一进程的多个线程共享同一地址空间,所以代码段,数据段是共享的,如果定义一个函数(存储在代码段),各线程都可以进行调用,如果定义个全局变量(存储在数据段),在各线程中都可以访问到,除此之外,各线程还共享以下进程资源和环境:
1.文件描述符表
2.每种信号的处理方式(SIG_IGN,SIG_DFL,用户自定义)
3.当前工作目录
4.用户id和组id
但有些资源是线程独享的:
1.线程id
2.上下文,包括各种寄存器的值,程序计数器和栈指针
3.栈空间
4.errno变量
5.信号屏蔽字
6.调度优先级
三. 线程的简单实用
1.创建线程
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
返回值:成功返回0,失败返回错误号。在一个线程中调pthread_create()创建新的线程后,当前线程从pthread_create()返回继续往下执行,新的线程所执行的代码由我们传给pthread_create的函数指针start_routine决定。
thread参数传入线程的id,void ( star_routine)(void )由用户进行撰写。
2.线程终止
void pthread_exit(void *retval)函数用于进程终止,传入一个id,调用exit()的话,主进程会终止。终止线程由三种方法:
1).从线程函数return。这种方法法对主线程不适用,从main函数return相当于调用exit。
2).一个线程可以调用pthread_cancel终止同一进程中的另一个线程。
3).线程可以调pthread_exit终自己。
retval是void *类型,其它线程可以调pthread_join获得这个指针。
3.线程等待
int pthread_join(pthread_t thread,void **retval);成功返回0,失败返回错误号。 线程的等待是以阻塞式等待,线程不等待会产生内存泄露(类似进程的僵尸进程)
4.进程取消
在合理范围内,线程可以自我或者被别人取消。取消后返回PTHREAD_CANCELED(它被定义为(void *)-1),取消调用函数pthread_cancel(id);
5.线程分离
在任何一个时间点上线程是可结合的(joinable)或者是分离的(detached)。一个可结合的线程能够被其他线程收回其资源和杀死。在被其他线程回收之前,它的存储器资源(例如栈)是不释放的。相反一个分离的线程是不能被其他线程回收或杀死的,它的存储器资源在它终时时由系统自动释放。
默认情况一个线程是可结合的,每一个可结合的线程都应该被显性的回收,既调用pthread_join()函数,分离调用函数pthread_detach。分离的这个函数是非阻塞的,可以立即返回。但为什么要分离呢?因为主进程在处理线程时,要处理不止一个,而每一个都需要被等待,然而join是阻塞式的,这样的话就只能处理一个线程,所以要加入分离,这样就可以处理多个线程。调用pthread_detach()后,这些子进程的状态会被设置为分离的,该线程运行结束会自动释放所有资源。
下面为测试代码:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void* thread1()
{
pthread_detach(pthread_self());//分离后仍可被等待
printf("pid is: %d, tid is: %d\n", getpid(),pthread_self());
return (void*)1;
}
int main()
{
pthread_t tid;
void *ret;
int err = pthread_create(&tid, NULL, thread1, NULL);
if (err != 0)
{
perror("pthread_create\n");
return err;
}
//如果直接运行等待代码,一般会等待成功,返回1
//如果在等待之前加入取消。等待错误,返回-1
// pthread_cancel(tid);
//线程可以自我取消也可以被取消,线程终止
//调用pthread_exit(tid);和取消同样用法。
int tmp = pthread_join(tid, &ret);
if (tmp == 0)
{
printf("wait success\n");
}
else
{
printf("wait failed\n");
}
printf(" pid is: %d, tid is: %d\n", getpid(),pthread_self());
sleep(1);
return 0;
}