多道程序设计和多线程有什么区别?
Posted crazy_itman
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多道程序设计和多线程有什么区别?相关的知识,希望对你有一定的参考价值。
多任务处理(英语:Computer multitasking)是指计算机同时运行多个程序的能力。多任务的一般方法是运行第一个程序的一段代码,保存工作环境;再运行第二个程序的一段代码,保存环境;……恢复第一个程序的工作环境,执行第一个程序的下一段代码……现代的多任务,每个程序的时间分配相对平均。计算机的早期,多任务被称作多道程序(multiprogramming)。多道程序是令CPU一次读取多个程序放入内存,先运行第一个程序直到它出现了IO操作。因为IO操作慢,CPU需要等待。为了提高CPU利用率,此时运行第二个程序。即,第n+1个程序得以执行的条件是第n个程序进行IO操作或已经运行完毕。这种方式每个程序的时间分配是不均等的,很可能第一个程序运行了几个小时而不出现IO操作,故第二个程序没有运行。在当初,这种情况是令人接受的。人们一次指定运行多个程序,过几个小时或一天后来看运行结果或拿走打印出来的文件。人们不需要实时获得每个程序的运行情况,只关心运行结果。
多线程编程中常见的错误有哪些?
在线程之间创建不必要的依赖关系(也读取共享资源)——在线程之间不必要地共享数据并使用锁访问数据不利于多线程程序的性能。因此,尽可能使用 MPICH 方法进行多线程编程是有益的。这个想法是将您的输入数据分成不重叠的集合,并将每个集合分配给一个线程。最后,您的主线程将负责从工作线程收集子结果,并将它们组合起来。这种方法也用于 STL 算法的并行版本的实现。
过度锁定——锁定尽可能少的共享数据和指令,并在对shared_data操作完成后立即解锁。
获取锁后休眠——在多线程程序中,共享数据是所有线程都在争夺的宝贵资源。线程设法使用锁获得对资源的独占访问权。如果您的代码获得了锁并进入休眠状态,它会在代码审查期间立即发出红旗。
获取锁后的 I/O 操作 - 与 CPU 操作相比,I/O 操作非常慢。网络操作也是如此。因此,一旦获得锁定,就应该避免执行 I/O 或网络操作。
创建太多线程 - C++ 中的 std::thread::hardware_concurrency() 可以让您很好地了解要在 C++ 程序中创建的最大线程数。如果你创建的线程比这更多,系统将在上下文切换中变得比执行你的程序更忙。
不使用 std::async - async 有助于将您的程序更像是一组任务,这比一堆线程更容易推理。异步是非阻塞的,也让你免于创建过多线程的烦恼。
不使用原子 - 原子是无锁的(仅适用于少数原始数据类型,基本用户定义的数据结构),因此比使用锁更快。
频繁请求空闲内存存储 - 您的程序只有一个内存管理器可用。当多个线程频繁调用“new”时,这与使用锁访问共享数据一样好。
Linux Kernel 本身是多线程的吗?
Linux 内核是一些聪明的程序员用了几年时间编写的一段高度优化的代码。Linux、*BSD、macOS、Windows NT 等任何流行内核的情况也是如此。您可以认为 Linux 没有针对给定功能的最佳算法,您可能是对的。然而,当任何 OS 开发人员发现更快更好的方法时,在许多情况下,可以获得足够的信息以允许具有竞争力的 OS Maintainer(包括 Linux)重新实现类似的功能。最后,您可以改进任何操作系统。但是,您不太可能找到像使用多线程这样的新方法这样容易实现的成果。如果是这样的话,有人已经在操作系统文献中记录了它。
Linux 多线程 — 是/否(语义问题):与标准程序不同并在其初始化之后,大多数操作系统大多是事件驱动的。中断机制是触发大多数服务任务(如调度程序)执行的机制。然后,在适当的时候,调度程序将调用内核线程。
中断是所有活动的基础:所有外围活动都是如此。当用户空间程序使用软件中断(例如:Open (filex))调用内核例程时也是如此。linux可以同时;打开文件、路由 TCP/IP 数据包、服务 Wi-Fi 适配器、以太网卡等等。但是,这些都不能被视为内核中的线程。因此,Linux 内核是多线程和事件驱动的。它可以执行多个任务/服务,所有任务/服务同时进行,并在适当的时候在多个处理器上执行。
内核中的重要优化:即使是最基本的内核也可以同时处理多个事件。单任务 MS-DOS 能够检测到 NMI 条件并开始执行第二个伪线程。<例如:CTRL-ALT-DELETE 序列>
重新进入:您可以安全地多次调用任何内核模块,同时在多个处理器上。该概念甚至适用于单处理器系统,其中可重入过程可以在其执行过程中被中断,然后在其先前的调用完成之前安全地重新进入。
中断抢占:Linux 确实允许某些中断抢占。它可以暂停低优先级中断的执行,以更好地响应高优先级中断。
细粒度内存锁:内核必须确定两个执行单元不会修改内存中的相同数据。Linux 有一个细粒度的内存锁结构。这确实意味着 TCP/IP 表更新可以发生在另一个内核执行单元修改调度表或文件 inode 表等时。也有可能当 Wi-Fi 驱动程序访问它处理的设备的内存表时,它可以在大部分时间完成它,而不会受到调度程序或其他执行单元的过多干扰。
实时项目场景中的多线程示例有哪些?
数学。想一想需要大量计算的数学问题,例如,求解一个庞大的线性方程组。如果您构建这样一个模型,您可以将计算拆分为多个不相交的块并独立执行每个块,那么这可以更快地完成。完成后,您只需组合每个线程的结果。另一个例子是矩阵乘法。请注意,为了使这些操作真正高效,您的每个线程都应该在自己的处理器上运行(这有时称为真正的并行性)
任务派发。当您有一个相关任务队列时,线程很有用,每个任务都可以独立执行。管理它们的实体称为线程池。线程池为要运行的任务提供了一些线程。把它想象成一个工厂,有多个管道和一排盒子,上面有关于如何构建其中内容的说明。一个工作人员从队列中取出一个盒子并将其放在管道上(如果有空闲的话)。Chromium 浏览器是这样构建的:它有几个线程,它们负责自己的事情。此外,一些线程有一个 MessageLoop 和 Tasks 队列,它们也是自己执行的。
图形用户界面应用程序。分离呈现和执行过程。当你构建一个 GUI 应用程序时,你永远不希望 GUI 冻结,因为用户会立即惊慌失措。为什么会结冰?当用户与您的应用程序交互时,它始终会处理一些数据:更新、读取和删除某些内容。这需要时间和处理能力。因此,为了避免这种情况,一个事件调度队列与您的 GUI 一起实现,以在单独的线程中处理所有数据处理,同时您的 GUI 保持完整的功能并可以轻松响应您的操作。同样,线程池在这里可能很有用。
联网。所有网络例程(例如下载图像)都可能需要时间并阻止您的应用程序执行。为避免这种情况,网络通常在另一个线程中执行,尽管您最常看到的是针对此问题的术语异步执行。尽管理论上它是一种完全不同的执行方法,但它与我们之前讨论的方法非常接近。
你的操作系统。您很可能正在运行一个现代操作系统,它们都采用多线程来保持自身的活力。操作系统必须同时控制很多事情,如果没有多线程,就不可能如此高效地完成所有事情。同样,前面讨论的所有概念都适用于此。
多道程序设计和多线程有什么区别?
多道程序
在多道程序系统中,主存中加载了一个或多个准备执行的程序。一次只有一个程序能够获得 CPU 来执行其指令(即,系统上最多运行一个进程),而所有其他程序都在等待轮到它们。多道程序设计的主要思想是最大限度地利用 CPU 时间。实际上,假设当前运行的进程正在执行 I/O 任务(根据定义,该任务不需要 CPU 来完成)。然后,操作系统可能会中断该进程并将控制权交给准备执行的其他主内存程序之一(即进程上下文切换). 这样,系统就不会浪费 CPU 时间来等待 I/O 任务完成,一个正在运行的进程会一直执行,直到它主动释放 CPU 或阻塞 I/O 操作。因此,多道程序设计的最终目标是只要有进程准备执行就可以让 CPU 保持忙碌。
请注意,为了使此类系统正常运行,操作系统必须能够将多个程序加载到主内存的不同区域并提供所需的保护以避免一个进程被另一个进程修改的机会。当内存中有多个程序时需要解决的其他问题是碎片当程序进入或离开主存储器时。另一个需要处理的问题是大型程序可能无法立即放入内存,这可以通过使用分页和虚拟内存来解决。
最后,请注意,如果有N就绪进程并且所有这些进程都高度受 CPU 限制(即,它们主要执行 CPU 任务而没有或很少执行 I/O 操作),在最坏的情况下,一个程序可能会等待所有其他N-1程序在执行之前完成。
多处理
多处理有时是指同时执行多个进程(程序)。这可能会产生误导,因为我们之前已经引入了术语“多道程序设计”来描述它。事实上,多处理指的是硬件(即 CPU 单元)而不是软件(即运行的进程)。如果底层硬件提供了多个处理器,那就是多处理。基本方案存在多种变化,例如,一个管芯上有多个内核,或者一个封装中有多个管芯,或者一个系统中有多个封装。无论如何,一个系统既可以通过同时运行多个程序来进行多道程序设计,也可以通过拥有多个物理处理器来进行多道处理。
多任务处理
多任务处理与多道程序设计具有相同的含义,但在更一般的意义上,因为它指的是同时运行多个(程序、进程、任务、线程)。当多个任务共享公共处理资源(例如,CPU 和内存)时,该术语用于现代操作系统。在任何时候,CPU 只执行一个任务,而其他任务等待轮到它们执行。当 CPU 被重新分配给另一个任务(即进程或线程上下文切换)时,就实现了并行的错觉。
多任务处理和多程序设计之间存在细微差别。一个任务在多任务操作系统中,它不是一个完整的应用程序,但当一个进程被划分为子任务时,它也可以指代“执行线程”。每个较小的任务都不会劫持 CPU,直到它像在旧的多道程序中一样完成,而是公平共享 CPU 时间,称为量子。
为了便于记忆,多道程序和多任务操作系统都是(CPU)分时系统。然而,在多道程序(较旧的操作系统)中,一个程序作为一个整体一直运行直到阻塞,而在多任务(现代操作系统)中,时间共享得到了最好的体现,因为每个运行的进程只占用相当一部分 CPU 时间。
多线程
到目前为止,我们已经将多道程序设计作为允许多个程序驻留在主内存中并(显然)同时运行的一种方式进行了讨论。然后,多任务处理是指多个任务通过共享 CPU 时间(显然)同时运行。最后,多处理描述了具有多个 CPU 的系统。那么,多线程从何而来?多线程是一种执行模型,允许单个进程在该进程的“上下文”中同时运行多个代码段(即线程)。您可以将线程视为共享父进程资源但独立执行的子进程。单个进程的多个线程可以在单 CPU 系统中共享 CPU 或(纯粹)在多处理系统中并行运行
为什么我们需要在单个进程上下文中有多个执行线程?好吧,例如考虑一个 GUI 应用程序,用户可以在其中发出需要很长时间才能完成的命令(例如,复杂的数学计算)。除非您将此命令设计为在单独的执行线程中运行,否则您将无法与主应用程序 GUI 交互(例如,更新进度条),因为它在计算进行时将无响应。当然,设计多线程/并发应用程序需要程序员处理在开发单线程、顺序应用程序时根本不会发生的情况。例如,当两个或多个线程尝试访问和修改共享资源时(竞争条件),程序员必须确保这不会使系统处于不一致或死锁状态。通常,此线程同步是使用 OS 原语解决的,例如mutexes和sempaphores 。
以上是关于多道程序设计和多线程有什么区别?的主要内容,如果未能解决你的问题,请参考以下文章