科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件实例解析C++/CLI线程之多任务

实例解析C++/CLI线程之多任务

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

从处理器的角度来看,线程是一个单独的执行流程,每个线程都有各自的寄存器及堆栈上下文。

作者:谢启东编译 来源:天极开发 2007年11月14日

关键字: 实例 C++ 线程 多任务

  • 评论
  • 分享微博
  • 分享邮件
简介

  从处理器的角度来看,线程是一个单独的执行流程,每个线程都有各自的寄存器及堆栈上下文。通常来说,在系统中只有一个处理器或处理器只有一个核心时,运行时环境在一个时间片内只能执行一个线程,当线程未能获取所需的资源时,线程的执行就会被中断,且会一直等到相关操作的完成,如I/O;或者在线程用完它的处理器时间片时,也会被中断下来等待。而处理器把执行流程从一个线程切换到另一个线程时,这称为"上下文切换";当某个线程变为"阻塞"状态,从而执行另一个线程时,系统有效地减少了处理器空闲时间,这称为"多任务"。

  当程序执行时,系统知道可以从磁盘上某处获取相关的指令及静态数据,程序会被分配到一组包含虚拟内存在内的地址空间,这个运行时上下文被称为"进程"。然而,在一个进程可以运行之前,它必须拥有至少一个线程,也就是说,当一个进程被创建时,它自动被赋予了一个线程,这称为"主线程"。但是话说回来,这个线程与之后这个进程所创建的线程相比,没有任何不同之处,它只不过恰好是这个进程的第一个线程而已。一般来说,在程序的控制之下,进程内的线程数在运行时会有所变化,任何线程都可以创建其他的线程,但不管怎样,线程不拥有它所创建的线程,所有进程内的线程都是作为一个整体属于这个进程。

  可把进程要完成的工作分成不同的"子任务",每一部分都由不同的线程来执行,这称为"多线程"。进程内的每个线程共享同样的地址空间与进程资源,当最后一个进程内的线程结束时,父进程就结束了。

  为何进程内要有多个线程呢?如果进程只有一个线程,那么它的执行流程是自上而下顺序执行的;当线程阻塞,而又没有其他的活动线程处于等待状态时,系统就会进入空闲状态;如果此时进程的子任务必须被顺序地执行,那么这种情况就不可避免,将花费大量的时间来等待。然而,绝大多数的进程都不是这样的,试想有这样一种情况,某个进程有多个选项,用户可以选择其中一些选项,由此产生的计算会使用内存或文件中的数据,并生成结果,如果能从中分出一些新的线程,那么进程不必等待前一个计算的结果,就可以继续接受新的计算请求。此外,通过指定线程的优先级,进程可只在更关键的线程阻塞时,才运行次关键的线程。

  在有多个线程的情况下,某些线程可负责程序的主要工作,而另一个线程可用于处理键盘和鼠标的输入。例如,用户可能会觉得前一次请求并不是期望的动作,从而希望取消由前一次请求产生的那一个线程,这时就可在某个下拉菜单中进行选择,由一个线程去终止另一个线程。

  另一个例子就是打印假脱机程序,它的任务是保持打印机尽可能地满载工作,并处理用户的打印请求;如果这个程序必须要等到前一项打印工作完成,才能接受新请求的话,用户可能会感到非常的不满。当然,程序也可周期性地停下打印工作,来查看是否有新的未处理请求(这称为"轮询"),但是,如果没有新请求,这将会非常浪费时间。另外,如果轮询的间隔时间太长,对处理新请求,还会造成延时;如果间隔太短,那么线程在轮询上花费的时间又太多。那么,为什么不让假脱机程序有两个线程呢?一个用于将打印工作传递到打印机,而另一个用于处于用户的请求,它们之间都相互独立运行;而当一个线程工作完成时,它要么结束自身,要么进入休眠状态。

  当处理并发的执行线程时,必须要首先了解两个重要的概念:原子性和重入性。一个原子变量或对象是作为一个整体被访问的,甚至于在异步操作的情况下也是如此--访问的是同一个变量或对象。举例来讲,如果一个线程正在更新一个原子变量或对象,而另一个线程在读取其内容,此时来讲,内容逻辑上的完整性是不可能被破坏的,所以,要么读取到旧值,要么读取到新值,而不会旧值新值各读一部分。通常来说,能被原子性访问的变量或对象,只是那些在硬件上能被原子性支持的类型,如字节(Byte)和字(Word)。C++/CLI中大多数的基本类型都确保具有原子性,剩下的类型也可被某种特定的实现支持原子性,但不能百分百保证。显而易见,一个实现了x与y坐标对的Point对象,不具有原子性,对Point值的写入,可能会被对其值的读取中断,结果就是,读取到了一个新的x值和一个旧的y值,反之亦然;同样地,数组也不可能被原子性地访问。正是因为大多数的对象不能被原子性地访问,所以必须使用一些同步形式来保证在某一时间,只有一个线程可操纵某个特定的对象。也正是因为此,C++/CLI分配给每一个对象、数据和类一个同步锁。

  一个重入的函数可由多个线程安全地并行执行。当线程开始执行一个函数时,在函数中分配的所有数据都来自栈或堆,但无论如何,对此调用来说,都是唯一的。如果在另一个线程仍处于工作状态时,本线程开始执行同一个函数,那么,每个线程中的数据都是相互独立的。然而,如果函数访问线程间共享的变量或文件时,则必须使用某些同步方法。
    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章