一、什么是线程?
1.线程是进程的一个执行流,在一个进程内部运行的多种执行流。
2. Linux下没有真正的线程,是用进程模拟的,因此线程也叫轻量级进程。
3. 线程在进程的进程地址空间运行,第一个pcb称之为主线程,一个进程至少有一个线程。
二、线程和进程共享和私有资源?
1.线程和进程共享: 数据段,代码段 、文件描述符表、每种信号的处理方式、当前工作的目录、用户id和线程组id
2.线程和进程私有:每个线程都有自己的栈结构、寄存器(包含上下文、各种计数器的值、程序计数器和栈指针)、线程 id、 errno变量(当线程异常退出时的错误退出码)、信号屏蔽字、调度优先级
三、线程优缺点?
优点:
1.线程创建销毁的代价比进程小。
2.线程切换的代价小,线程切换只需要切换其上下文。
3.线程间通信比进程好。(由于线程共享进程的地址空间,因此通信可以很随意)
4.在等待慢速 I/O操作结束的同时,程序可执行其他的计算任务。(比如可以边下载电影边听歌)
5.计算密集型应用,为了能在多处理器系统上运行,将计算分解到多个线程中实现。
6.I/O密集型应用,为了提高性能,将I/O操作重叠,线程可以同时等待不同的I/O操作。
缺点:
1.性能损失:指的是操作系统增加了额外的同步和调度开销,而可用的资源不变。
2.健壮性降低:线程退出会导致整个进程退出。
3.缺乏访问控制:多线程共享地址空间,但为了维护公共资源,又引入锁,信号量等机制,使用不当会造成死锁。
4.编程难度提高:多进程提高了编程难度和定位问题的难度。
四、POSIX线程库
在操作系统看来,它不管什么进程线程,只以PCB为准,只有在用户态里才有线程的概念。一般实现线程会用到一个POSIX线程库,在这里可以通过调用POSIX库里的函数来实现有关线程的各种操作。
1.线程创建:
#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);
参数:
1> thread:线程id,线程标识符,线程栈的起始地址,输出型参数,类型为 pthread_t,本质是long int 型。
2>attr:线程属性,NULL。
3>函数指针:新线程执行该函数指针指向的代码,线程回调函数
4>arg:传递给函数指针指向的函数的参数,线程回调函数的参数
返回值:成功返回0,失败返回错误码。
2.线程终止:
1>线程return:如果线程通过return返回,那么retval所指向的单元里存放的是tread函数的返回值(main函数创建一个新线 程,新线程执行完自己的函数,使用return退出,那么返回值就是退出码)
2>线程exit:线程调用exit终止的,表示进程退出。
3>使用pthread_exit():线程自己调用函数终止,pthread_ jion()函数里的retval(退出码)就是pthread_exit的参数。
#include <pthread.h>
void pthread_exit(void *retval);
//其中参数retval是要退出后结果,其他线程可以通过pthread_join得到该值.
//需要注意的是,retval要求指向的地址不会因为线程退出而失效,这说明用线程变量存储返回值是不靠谱的.
4>线程取消:如果线程通过pthread_ cancel被别的线程异常终止,则retval就是PTHREAD_ CANCELED(-1)。
#include <pthread.h>
int pthread_cancel(pthread_t thread);
//可以终止自己的线程也可以终止别人的线程
//成功返回0,失败返回-1
//终止自己算是成功退出,返回0,终止别的进程,则那个进程算是失败退出,返回-1;
3.线程等待:和进程中的waitpid有点像。父进程如果不进行wait,子进程退出后就会成为僵尸进程,线程也一样,joinable的线程
在退出后如果没有其他线程调用pthread_join 接住它的退出状态,那它也同样不会释放线程的资源。调pthread_join
的线程在接收到返回状态前会陷入阻塞。父进程可以等待任何一个子进程退出,但是线程必须明确指定要等待的线
程id。线程无上下级关系,即便主线程调用pthread_exit退出了,进程还是能继续运行。
#include <pthread.h>
int pthread_join(pthread_t thread, //要等待的线程ID
void **retval);//用于接收线程退出的退出码
4.线程分离:新创建的线程默认是joinable的,如果不关心线程的退出状态,那么可以将其分离,表示告诉操作系统我退出后请你
帮我回收我的资源,随着线程结束马上交出栈资源,所以也无需其他线程join它。
#include <pthread.h>
int pthread_deatch(pthread_t thread);//将pthread_thread对应的线程设为分离态的线程
pthread_detach(pthread_self());//普遍的做法是线程内部自己修改分离状态