linux多线程设计 1

发布 2022-09-20 17:48:28 阅读 3007

1linux线程概述。

1.1线程概述。

前面已经提到,进程是系统中程序执行和资源分配的基本单位。每个进程都拥有自己的数据段、**段和堆栈段,这就造成了进程在进行切换等操作时都需要有比较复杂的上下文切换等动作。为了进一步减少处理机的空转时间,支持多处理器以及减少上下文切换开销,进程在演化**现了另一个概念——线程。

它是进程内独立的一条运行路线,处理器调度的最小单元,也可以称为轻量级进程。线程可以对进程的内存空间和资源进行访问,并与同一进程中的其他线程共享。因此,线程的上下文切换的开销比创建进程小很多。

同进程一样,线程也将相关的执行状态和存储变量放**程控制表内。一个进程可以有多个线程,也就是有多个线程控制表及堆栈寄存器,但却共享一个用户地址空间。要注意的是,由于线程共享了进程的资源和地址空间,因此,任何线程对系统资源的操作都会给其他线程带来影响。

由此可知,多线程中的同步是非常重要的问题。在多线程系统中,进程与进程的关系如图1所示。

图1进程与线程关系。

1.2线程机制的分类和特性。

线程按照其调度者可以分为用户级线程和核心级线程两种。

1)用户级线程。

用户级线程主要解决的是上下文切换的问题,它的调度算法和调度过程全部由用户自行选择决定,在运行时不需要特定的内核支持。在这里,操作系统往往会提供一个用户空间的线程库,该线程库提供了线程的创建、调度和撤销等功能,而内核仍然仅对进程进行管理。如果一个进程中的某一个线程调用了一个阻塞的系统调用函数,那么该进程包括该进程中的其他所有线程也同时被阻塞。

这种用户级线程的主要缺点是在一个进程中的多个线程的调度中无法发挥多处理器的优势。

2)轻量级进程。

轻量级进程是内核支持的用户线程,是内核线程的一种抽象对象。每个线程拥有一个或多个轻量级线程,而每个轻量级线程分别被绑定在一个内核线程上。

3)内核线程。

这种线程允许不同进程中的线程按照同一相对优先调度方法进行调度,这样就可以发挥多处理器的并发优势。

现在大多数系统都采用用户级线程与核心级线程并存的方法。一个用户级线程可以对应一个或几个核心级线程,也就是“一对一”或“多对一”模型。这样既可满足多处理机系统的需要,也可以最大限度地减少调度开销。

使用线程机制大大加快上下文切换速度而且节省很多资源。但是因为在用户态和内核态均要实现调度管理,所以会增加实现的复杂度和引起优先级翻转的可能性。一个多线程程序的同步设计与调试也会增加程序实现的难度。

2linux线程编程。

2.1线程基本编程。

这里要讲的线程相关操作都是用户空间中的线程的操作。在linux中,一般pthread线程库是一套通用的线程库,是由posix提出的,因此具有很好的可移植性。

1)函数说明。

创建线程实际上就是确定调用该线程函数的入口点,这里通常使用的函数是pthread_create()。**程创建以后,就开始运行相关的线程函数,在该函数运行完之后,该线程也就退出了,这也是线程退出一种方法。另一种退出线程的方法是使用函数pthread_exit(),这是线程的主动行为。

这里要注意的是,在使用线程函数时,不能随意使用exit()退出函数进行出错处理,由于exit()的作用是使调用进程终止,往往一个进程包含多个线程,因此,在使用exit()之后,该进程中的所有线程都终止了。因此,**程中就可以使用pthread_exit()来代替进程中的exit()。

由于一个进程中的多个线程是共享数据段的,因此通常**程退出之后,退出线程所占用的资源并不会随着线程的终止而得到释放。正如进程之间可以用wait()系统调用来同步终止并释放资源一样,线程之间也有类似机制,那就是pthread_join()函数。pthread_join()可以用于将当前线程挂起来等待线程的结束。

这个函数是一个线程阻塞的函数,调用它的函数将一直等待到被等待的线程结束为止,当函数返回时,被等待线程的资源就被收回。

前面已提到线程调用pthread_exit()函数主动终止自身线程。但是在很多线程应用中,经常会遇到在别的线程中要终止另一个线程的执行的问题。此时调用pthread_cancel()函数实现这种功能,但在被取消的线程的内部需要调用pthread_setcancel()函数和pthread_setcanceltype()函数设置自己的取消状态,例如被取消的线程接收到另一个线程的取消请求之后,是接受还是忽略这个请求;如果接受,是立刻进行终止操作还是等待某个函数的调用等。

2)函数格式。

表1列出了pthread_create()函数的语法要点。

表pthread_create()函数语法要点。

表2列出了pthread_exit()函数的语法要点。

表2pthread_exit()函数语法要点。

表3列出了pthread_join()函数的语法要点。

表3 pthread_join()函数语法要点。

表4列出了pthread_cancel()函数的语法要点。

表4pthread_cancel()函数语法要点。

3)函数使用。

以下实例中创建了3个线程,为了更好地描述线程之间的并行执行,让3个线程重用同一个执行函数。每个线程都有5次循环(可以看成5个小任务),每次循环之间会随机等待1~10s的时间,意义在于模拟每个任务的到达时间是随机的,并没有任何特定规律。

#include <>

#include <>

#include <>

#define thread_number 3/*线程数*/

#define repeat_number 5 /*每个线程中的小任务数*/

#define delay_time_levels10.0 /*小任务之间的最大时间间隔*/

void *thrd_func(void *arg)

/*线程函数例程 */

int thrd_num = int)arg;

int delay_time = 0;

int count = 0;

printf("thread %d is starting", thrd_num);

for (count = 0; count < repeat_number; count++)

printf("thread %d finished", thrd_num);

pthread_exit(null);

int main(void)

pthread_t thread[thread_number];

int no = 0, res;

void * thrd_ret;

srand(time(null));

for (no = 0; no < thread_number; no++)

printf("create treads success waiting for threads to finish...n");

for (no = 0; no < thread_number; no++)

/* 等待线程结束 */

res = pthread_join(thread[no], thrd_ret);

if (!res)

15 多线程作业

三 判断题。1.进程是线程thread内部的一个执行单元,它是程序中一个单一顺序控制流程。2.一个进程可以包括多个线程。两者的一个主要区别是 线程是资源分配的单位,而进程cpu调度和执行的单位。3.用new关键字建立一个线程对象后,该线程对象就处于新生状态。处于新生状态的线程有自己的内存空间,通过调...

linux实验 1

北京 xx 大学 2014学年 2015学年第 1 学期 linux应用实验报告书。实验题目 实验三 gnu下编译器和调试器的使用初步 实验环境 linux环境。实验目的 通过调试一个有问题的程序,进一步熟练使用 vi 操作,而且熟练掌握 gcc 编译及 gdb 的调试命令,通过对有问题程序的跟踪调...

Linux 习题 1

大作业 一 一 填空题。1 linux中除图形登录外还可以使用命令提示行进行登录。2 如果要访问网络中的另一台电脑,可以通过命令方式进行登录。3 shell 是一个类似于 dos 的命令行解释工具。4 shell的概念最初是在 unix 操作系统中形成和得到广泛应用的。5 linux中的shell有...