7、linux多线程编程

项目、任务: ①.多线程编程思想的理论知识学习 ②.完成给出的几个多线程编程的实验 注:这部分内容难度较大,内容也较多,建议花2-3天的时间来理解和消化。 考核内容: ①.完成lab1,lab2的实验 ②.完成本章最后的作业提交任务和反馈内容

任务、步骤: 任务一: Linux下C++的多线程编程,多线程引入原因及简单的编程训练。

  1. 多线程引入原因:  线程(thread)技术早在60年代就被提出,但真正应用多线程到操作系统中去,是在80年代中期,solaris是这方面的佼佼者。传统的Unix也支持线程的概念,但是在一个进程(process)中只允许有一个线程,这样多线程就意味着多进程。现在,多线程技术已经被许多操作系统所支持,包括Windows\/NT,当然,也包括Linux。   为什么有了进程的概念后,还要再引入线程呢?使用多线程到底有哪些好处?什么的系统应该选用多线程?我们首先必须回答这些问题。   使用多线程的理由之一是和进程相比,它是一种非常"节俭"的多任务操作方式。我们知道,在Linux系统下,启动一个新的进程必须分配给它独立的地址空间,建立众多的数据表来维护它的代码段、堆栈段和数据段,这是一种"昂贵"的多任务工作方式。而运行于一个进程中的多个线程,它们彼此之间使用相同的地址空间,共享大部分数据,启动一个线程所花费的空间远远小于启动一个进程所花费的空间,而且,线程间彼此切换所需的时间也远远小于进程间切换所需要的时间。据统计,总的说来,一个进程的开销大约是一个线程开销的30倍左右,当然,在具体的系统上,这个数据可能会有较大的区别。   使用多线程的理由之二是线程间方便的通信机制。对不同进程来说,它们具有独立的数据空间,要进行数据的传递只能通过通信的方式进行,这种方式不仅费时,而且很不方便。线程则不然,由于同一进程下的线程之间共享数据空间,所以一个线程的数据可以直接为其它线程所用,这不仅快捷,而且方便。当然,数据的共享也带来其他一些问题,有的变量不能同时被两个线程所修改,有的子程序中声明为static的数据更有可能给多线程程序带来灾难性的打击,这些正是编写多线程程序时最需要注意的地方。   除了以上所说的优点外,不和进程比较,多线程程序作为一种多任务、并发的工作方式,当然有以下的优点:   1) 提高应用程序响应。这对图形界面的程序尤其有意义,当一个操作耗时很长时,整个系统都会等待这个操作,此时程序不会响应键盘、鼠标、菜单的操作,而使用多线程技术,将耗时长的操作(time consuming)置于一个新的线程,可以避免这种尴尬的情况。   2) 使多CPU系统更加有效。操作系统会保证当线程数不大于CPU数目时,不同的线程运行于不同的CPU上。   3) 改善程序结构。一个既长又复杂的进程可以考虑分为多个线程,成为几个独立或半独立的运行部分,这样的程序会利于理解和修改。   下面我们先来尝试编写一个简单的多线程程序。

  2. 简单的多线程编程 Linux系统下的多线程遵循POSIX线程接口,称为pthread。编写Linux下的多线程程序,需要使用头文件pthread.h,连接时需要使用库libpthread.a。顺便说一下,Linux下pthread的实现是通过系统调用clone()来实现的。clone()是Linux所特有的系统调用,它的使用方式类似fork,关于clone()的详细情况,有兴趣的读者可以去查看有关文档说明。下面我们展示一个最简单的多线程程序threads.cpp。

\/\/Threads.cpp

include

include

include using namespace std;

void _thread(void _ptr) { for(int i = 0;i < 3;i++) { sleep(1); cout << "This is a pthread." << endl; } return 0; } int main() { pthread_t id; int ret = pthread_create(&id, NULL, thread, NULL); if(ret) { cout << "Create pthread error!" << endl; return 1; } for(int i = 0;i < 3;i++) { cout << "This is the main process." << endl; sleep(1); } pthread_join(id, NULL); return 0; } 我们编译并运行此程序,可以得到如下结果:   This is the main process.   This is a pthread.   This is the main process.   This is the main process.   This is a pthread.   This is a pthread.   再次运行,我们可能得到如下结果:   This is a pthread.   This is the main process.   This is a pthread.   This is the main process.   This is a pthread.   This is the main process. 前后两次结果不一样,这是两个线程争夺CPU资源的结果。上面的示例中,我们使用到了两个函数,pthread_create和pthread_join,并声明了一个pthread_t型的变量。   pthread_t在头文件\/usr\/include\/bits\/pthreadtypes.h中定义:

它是一个线程的标识符。 (1)函数pthread_create用来创建一个线程,它的原型为:

第一个参数为指向线程标识符的指针; 第二个参数用来设置线程属性; 第三个参数是线程运行函数的起始地址; 第四个参数是运行函数的参数。 这里,我们的函数thread不需要参数,所以最后一个参数设为空指针(NULL)。第二个参数我们也设为空指针,这样将生成默认属性的线程。当创建线程成功时,函数返回0,若不为0则说明创建线程失败,常见的错误返回代码为EAGAIN和EINVAL。前者表示系统限制创建新的线程,例如线程数目过多了;后者表示第二个参数代表的线程属性值非法。创建线程成功后,新创建的线程则运行参数三和参数四确定的函数,原来的线程则继续运行下一行代码。 (2)函数pthread_join用来等待一个线程的结束。函数原型为:

第一个参数为被等待的线程标识符; 第二个参数为一个用户定义的指针,它可以用来存储被等待线程的返回值。这个函数是一个线程阻塞的函数,调用它的函数将一直等待到被等待的线程结束为止,当函数返回时,被等待线程的资源被收回。 一个线程的结束有两种途径,一种是象我们上面的例子一样,函数结束了,调用它的线程也就结束了; (3)另一种方式是通过函数pthread_exit来实现。它的函数原型为:

唯一的参数是函数的返回代码,只要pthread_join中的第二个参数thread_return不是NULL,这个值将被传递给thread_return。最后要说明的是,一个线程不能被多个线程等待,否则第一个接收到信号的线程成功返回,其余调用pthread_join的线程则返回错误代码ESRCH。

任务二: 完成lab1,lab2的实验 步骤: Lab1、线程创建程序设计

实验要求:在程序中创建一个线程,并向该线程处理函数传递一个结构体作为参 数。 功能描述:通过 pthread_create 创建一个线程并传入一个结构体参数,再 在线程中接收到这个参数并把参数内容打印出来。

编写实验代码thread_struct.c,可以参考上图代码。 使用命令 gcc thread_struct.c –o thread_struct -lpthread 编译thread_struct.c。如图,可以看到生成了可执行文件 thread_struct。 运行 thread_struct,如图所示,可以看到在线程执行函数中打印出了在主函数 中赋值的结构体,即将这个结构体传递进了线程执行函数中。

Lab2、线程等待程序设计

实验要求:在程序中创建一个线程,进程需等待该线程执行结束后才能继续执 行。 功能描述:通过 pthread_join 阻塞等待,直至相应线程结束。

线程等待的方法: 创建一个线程,在进程中通过调用函数 pthread_join()等待线程结束,这个 函数是一个线程阻塞的函数, 调用它的进程将一直等待到被等待的线程结束 为止,当函数返回时,被等待线程的资源被收回

编写实验代码thread_join.c,可以参考上图代码。

使用命令 gcc thread_join.c –o thread_join -lpthread 编译 thread_join.c。 如图所示,可以看到生成了可执行文件 thread_join。运行 thread_join 如图2所示,可以看到创建线程而没有调用 thread_join 之前线程和进程是同时运 行的,调用 thread_join 之后进程阻塞直到线程退出。

图2 编译及运行程序

作业提交: 1.请完成lab1实验。并将实验结果截图以及代码提交至作业处 2.请完成lab2实验。并将实验结果截图以及代码提交至作业处 内容反馈: 请提交您在这一小阶段项目完成的过程中遇到的问题和您的意见及建议提交至内容反馈中,以便我们更好的为大家解答和改进,衷心的感谢。

results matching ""

    No results matching ""

    results matching ""

      No results matching ""