浅谈Linux中的线程

来源:互联网 发布:类似tnt的网络邮箱 编辑:程序博客网 时间:2024/05/18 16:15

1.线程概念

  先来看看百度百科对线程的解释:

       线程,有时被称为轻量级进程(Lightweight Process,LWP),是程序执行流的最小单元。一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成。另外,线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。由于线程之间的相互制约,致使线程在运行中呈现出间断性。线程也有就绪、阻塞和运行三种基本状态。就绪状态是指线程具备运行的所有条件,逻辑上可以运行,在等待处理机;运行状态是指线程占有处理机正在运行;阻塞状态是指线程在等待一个事件(如某个信号量),逻辑上不可执行。每一个程序都至少有一个线程,若程序只有一个线程,那就是程序本身。

  总结一下就是需要在⼀个进程中同时执行多个控制流程的时候,线程就派上了⽤场。而实际上在Linux下无真正意义上的线程,Linux中的线程是由进程模拟出来的。进程是承担分配系统资源的基本实体,线程是操作系统或进程调度的最小单位,线程是进程的执行分支,线程是在进程内部(地址空间)执行的。


2.线程与进程的区别和联系

进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,是系统进行资源分配和调度的一个独立单位.线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源.
一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行.

区别可以总结如下几点:

a.地址空间和其它资源:进程间相互独立,同一进程的各线程间共享。某进程内的线程在其它进程不可见。

b.通信:进程间通信IPC,线程间可以直接读写进程数据段(如全局变量)来进行通信——需要进程同步和互斥手段的辅助,以保证数据的一致性。

c.调度和切换:线程上下文切换比进程上下文切换要快得多。

d.在多线程OS中,进程不是一个可执行的实体。

各线程共享以下进程资源和环境: 

1. 文件描述符表 

2. 每种信号的处理⽅方式(SIG_IGN、SIG_DFL或者⾃自定义的信号处理函数)

3. 当前工作目录

4. 用户id和组id 

私有资源:

1. 线程id 

2. 上下文,包括各种寄存器的值、程序计数器和栈指针

3. 栈空间

4. errno变量

5. 信号屏蔽字 

6. 调度优先级


3.线程的创建

先来看看创建一个线程我们要使用的函数原型:

int pthread_create(pthread_t *thread,pthread_attr_t *attr,void *(*start_routine)(void *),void *arg);

第一个参数为线程id,第二个参数为线程属性设置为NULL,第三个参数是一个函数指针,目的是当前线程从pthread_create()返回继续往下执行,而新的线程所执行的代码由我们传给pthread_create的函数指针start_routine决定。最后一个参数是传递函数的参数。 返回值:成功返回0,失败返回错误号。

下来看看具体代码:

运行结果:

4.线程等待

等待一个线程我们要用到的函数是phread_join(),原型如下:

1 int pthread_join(pthread_t thread, void **retval);

成功返回0,失败返回错误号。

具体代码如下:

运行3秒之后产生结果如下:

5.线程终止:

线程退出方式:

1.从线程函数内部return可以终止这个线程,但如果是main函数,则整个线程退出。

2.调用pthread_exit()函数终止同一进程中的另一个线程。

函数原型如下:

int pthread_cancel(pthread_t thread);

具体代码如下:

运行结果:

3.线程可以调用pthread_exit终止⾃自己。

函数原型如下:

void pthread_exit(void *retval);

具体代码如下:


结果如下:


6.线程的分离与结合

在任何一个时间点上,线程是可结合的(joinable)或者是分离的(detached)。⼀一个可结合的线程能够被其他线程收回其资源和杀死。在被其他线程回收之前,它的存储器资源(例如栈)是不释放的。相反,⼀一个分离的线程是不能被其他线程回收或杀死的,它的存储器 资源在它终⽌止时由系统⾃自动释放。

一般情况下,线程终止后,其终止状态⼀一直保留到其它线程调用pthread_join获取它的状态为止。 但是线程也可以被置为detach 状态,这样的线程一旦终止就立刻回收它占用的所有资源,而不保留终止状态。不能对一个已经处于detach状态的线程调用pthread_join,这样的调将返回EINVAL。 对一个尚未detach的线程调用pthread_join或pthread_detach都可以把该线程置为detach状态,也 就是说,不能对同一线程调用两次pthread_join,或者如果已经对一个线程调用了pthread_detach就不能再调用pthread_join了。

int pthread_detach(pthread_t thread);
由于调用pthread_join后,如果该线程没有运行结束,调用者会被阻塞,在有些情况下我们并不希望如此。例如,在Web服务器中当主线程为每个新来的连接请求创建一个子线程进行处理的时候,主线程并不希望因为调用pthread_join而阻塞(因为还要继续处理之后到来的连接请求),这时可以在子线程中加入代码

pthread_detach(pthread_self())

或者利用父线程调用

pthread_detach(thread_id)

这将该子线程的状态设置为分离的(detached),如此一来,该线程运行结束后会自动释放所有资源.
具体代码如下:

运行结果如下:



原创粉丝点击