网站统计工具是什么意思,口碑营销的策略技巧,佛山网站建设正规公司,wordpress 手册插件【图书推荐】《Linux C与C一线开发实践#xff08;第2版#xff09;》_linux c与c一线开发实践pdf-CSDN博客《Linux C与C一线开发实践#xff08;第2版#xff09;#xff08;Linux技术丛书#xff09;》(朱文伟#xff0c;李建英)【摘要 书评 试读】- 京东图书 (jd.com…【图书推荐】《Linux C与C一线开发实践第2版》_linux c与c一线开发实践pdf-CSDN博客《Linux C与C一线开发实践第2版Linux技术丛书》(朱文伟李建英)【摘要 书评 试读】- 京东图书 (jd.com)
8.2.1 操作系统和多线程
要在应用程序中实现多线程必须有操作系统的支持。Linux 32位或64位操作系统对应用程序提供了多线程的支持所以Windows NT/2000/XP/7/8/10是多线程操作系统。根据进程与线程的支持情况可以把操作系统大致分为如下几类
1单进程、单线程MS-DOS大致是这种操作系统。
2多进程、单线程多数UNIX及类UNIX的Linux是这种操作系统。
3多进程、多线程Win32Windows NT/2000/XP/7/8/10等、Solaris 2.x和OS/2都是这种操作系统。
4单进程、多线程VxWorks是这种操作系统。
具体到Linux C的开发环境它提供了一套POSIX API函数来管理线程用户既可以直接使用这些POSIX API函数也可以使用C自带的线程类。作为一名Linux C开发者这两者都应该会使用因为在Linux C程序中这两种方式都有可能出现。
8.2.2 线程的基本概念
现代操作系统大多支持多线程概念每个进程中至少有一个线程所以即使没有使用多线程编程技术进程也含有一个主线程所以也可以说CPU中执行的是线程线程是程序的最小执行单位是操作系统分配CPU时间的最小实体。一个进程的执行说到底是从主线程开始的如果需要可以在程序任何地方开辟新的线程其他线程都是由主线程创建的。一个进程正在运行也可以说是一个进程中的某个线程正在运行。一个进程的所有线程共享该进程的公共资源比如虚拟地址空间、全局变量等。每个线程也可以拥有自己私有的资源如堆栈、在堆栈中定义的静态变量和动态变量、CPU寄存器的状态等。
线程总是在某个进程环境中创建的并且会在这个进程内部销毁。线程和进程的关系是线程是属于进程的线程运行在进程空间内同一进程所产生的线程共享同一内存空间当进程退出时该进程所产生的线程都会被强制退出并清除。线程可与属于同一进程的其他线程共享进程所拥有的全部资源但是其本身基本上不拥有系统资源只拥有一点在运行中必不可少的信息如程序计数器、一组寄存器和线程栈线程栈用于维护线程在执行代码时需要的所有函数参数和局部变量。
相对于进程来说线程所占用的资源更少。比如创建进程系统要为它分配很大的私有空间占用的资源较多而对于多线程程序来说由于多个线程共享一个进程地址空间因此占用的资源较少。此外进程间切换时需要交换整个地址空间而线程间切换时只是切换线程的上下文环境因此效率更高。在操作系统中引入线程带来的主要好处是
1在进程内创建、终止线程比创建、终止进程要快。
2同一进程内线程间的切换比进程间的切换要快尤其是用户级线程间的切换。
3每个进程具有独立的地址空间而该进程内的所有线程共享该地址空间因此线程的出现可以解决父子进程模型中子进程必须复制父进程地址空间的问题。
4线程对解决客户/服务器模型非常有效。
虽然多线程给应用开发带来了不少好处但并不是所有情况下都要去使用多线程要具体问题具体分析。通常在下列情况下可以考虑使用多线程
1应用程序中的各任务相对独立。
2某些任务耗时较多。
3各任务有不同的优先级。
4一些实时系统应用。
值得注意的是一个进程中的所有线程共享它们父进程的变量但同时每个线程可以拥有自己的变量。
8.2.3 线程的状态
一个线程在从创建到结束这一生命周期中总是处于下面4个状态中的一个。
1就绪态
线程能够运行的条件已经满足只是在等待处理器处理器要根据调度策略来把就绪态的线程调度到处理器中运行。处于就绪态的原因可能是线程刚刚被创建刚创建的线程不一定马上运行一般先处于就绪态也可能是刚刚从阻塞状态中恢复还可能是因被其他线程抢占而处于就绪态。
2运行态
运行态表示线程正在处理器中运行正占用着处理器。
3阻塞态
由于在等待处理器之外的其他条件而无法运行的状态叫作阻塞态。这里的其他条件包括I/O操作、互斥锁的释放、条件变量的改变等。
4终止态
终止态就是线程的线程函数运行结束或被其他线程取消后处于的状态。处于终止态的线程虽然已经结束了但它所占资源还没有被回收而且还可以被重新复活。我们不应该长时间让线程处于这种状态线程处于终止态后应该及时进行资源回收下面会讲到如何回收。
8.2.4 线程函数
线程函数就是线程创建后进入运行态后要执行的函数。执行线程说到底就是执行线程函数。这个函数是我们自定义的然后在创建线程时把我们的函数作为参数传入线程创建函数。
同理中断线程的执行就是中断线程函数的执行以后再恢复线程的时候就会在前面线程函数暂停的地方继续执行下面的代码。结束线程也就不再运行线程函数。线程的函数可以是一个全局函数或类的静态函数比如在POSIX线程库中它通常这样声明
void *ThreadProc (void *arg)
其中参数arg指向要传给线程的数据这个参数是在创建线程的时候作为参数传入线程创建函数中的。函数的返回值应该表示线程函数运行的结果成功还是失败。注意函数名ThreadProc可以是自定义的函数名这个函数是用户自己先定义好然后由系统来调用。
8.2.5 线程标识
既然句柄是用来标识线程对象的那线程本身用什么来标识呢在创建线程的时候系统会为线程分配唯一的ID作为线程的标识这个ID从线程创建开始就存在一直伴随着线程的结束才消失。线程结束后该ID就自动不存在我们不需要去显式清除它。
通常线程创建成功后会返回一个线程ID。
8.2.6 C多线程开发的两种方式
在Linux C开发环境中通常有两种方式来开发多线程程序一种是利用POSIX多线程API函数来开发多线程程序另一种是利用C自带线程类来开发多线程程序。这两种方式各有利弊。前一种方法比较传统后一种方法比较新是C11推出的方法。为何C程序员也要熟悉POSIX多线程开发呢这是因为C11以前在C里面使用多线程一般都是利用POSIX多线程API或者把POSIX多线程API封装成类再在公司内部供大家使用。因此一些老项目都是和POSIX多线程库相关的这也使得我们必须熟悉它因为很可能进入公司后会要求维护以前的程序代码。而C自带线程类很可能在以后开发新的项目时会用到。总之技多不压身。