程序、进程、线程
当计算机出现多核处理器后,每个“核”便可以同时执行不同的行程,这时,我们需要让操作系统和应用程序也实现并行化执行。这样的话,“程序”的概念,已经无法描述其内存中的执行情况,它是静态的,为此人们引入“进程”的概念:一个具有独立功能的程序关于某个数据集合的一次运行活动。他是动态的概念,具体可通过程序计数器的值和处理寄存器的内容来表示。进程可分为系统进程和用户进程,从实现角度看,是一种数据结构,它清晰地刻画了动态系统的内在规律,通过进程,操作系统有效管理和调度进入计算机系统主存储器运行的程序。而一个进程又是由多个线程所组成的,线程是程序中的一个执行流,每个线程都有自己的专有寄存器(栈指针、程序计数器等),但代码区是共享的,即不同的线程可以执行同样的函数。多线程是指程序中包含多个执行流,即在一个程序中可以同时运行多个不同的线程来执行不同的任务,也就是说允许单个程序创建多个并行执行的线程来完成各自的任务。
图1线程的概念
图2进程和线程的关系
Windows是一个多任务的系统,如果你使用的是windows 2000及 其以上版本,你可以通过任务管理器查看当前系统运行的程序和进程。早期的windows系统是没有“线程”概念的,整个系统只能运行着一个执行线程,这可能阻塞其他任务的执行,带来极其差的用户体验,基于上述及其操作系统的健壮性,可靠性等,windows引入了“线程”的概念。 线程可以看作是对CPU的虚拟。在windows下,进程是拥有自己的内存、文件句柄和其他系统资源的运行程序。进程的所有代码和数据空间都可以提供给该进程中的所有线程,例如,两个线程可以访问相同的全局变量。而线程由操作系统来进行管理,每个线程都有它自己的堆栈。Windows提供了两种线程,辅助线程和用户界面线程。两种线程均为MFC库所支持。用户界面线程通常有窗口,因此,它具有自己的消息循环。辅助线程没有窗口,因此,它不需要处理消息。辅助线程比较易于编程,而且通常更加有用。
多线程是这样一种机制,它允许在程序中并发执行多个指令流,每个指令流都称为一个线程,彼此间互相独立。线程又称为轻量级进程,它和进程一样拥有独立的执行控制,由操作系统负责调度。多线程是多任务的特殊形式,是为了使得多个线程并行的工作以完成多项任务,以提高系统的效率,是在同一时间需要完成多项任务的时候被实现的。使用多线程有下面几个优点:
1)使用线程可以把占据长时间的程序中的任务放到后台去处理
2)用户界面可以更加吸引人,这样比如用户点击了一个按钮去触发某些事件的处理,可以弹出一个进度条来显示处理的进度
3)程序的运行速度可能加快
4)在一些等待的任务实现上如用户输入、文件读写和网络收发数据等,我们可以释放一些珍贵的资源如内存占用等等。
然而线程也存在一些不利的方面,为正确使用线程,我们必须认识到:
1)线程也是程序,所以线程需要占用内存,线程越多占用内存也越多;
2)多线程需要协调和管理,所以需要CPU时间跟踪线程
3)线程之间对共享资源的访问会相互影响,必须解决竞用共享资源的问题
4)线程太多会导致控制太复杂,最终可能造成很多Bug
C++是为所有类型的程序设计类型设计的,从嵌入式系统(在执行环境中没有操作系统)到高度分布的、基于GUI的终端用户应用程序以及介于二者之间的一切程序。因此,C++不能够对它的执行环境加入明显的限制。内建的对多线程的支持将会从根本上将C++限制在那些支持多线程的环境中,从而阻止了在不使用线程的环境中开发软件时使用C++。在最后的分析中,没有内建的对多线程的支持是C++的一个主要优点,因为这样可以使用对目标执行环境最高效的方式编写程序。记住,C++的功能无处不在。多线程的情况很明显是一种“简单就好”的情况。
多线程改变了程序的基本结构。不同于按照严格的线性方式执行的单线程程序,多线程程序并发地执行它自身的各个部分。这样,所有的多线程程序都包含了相似的元素。因此,多线程程序的主要问题是管理线程之间的交互。C++没有包含任何对多线程应用程序的内建的支持。相反,它依赖于操作系统提供这个特性。考虑到Java和C#都提供了内建的多线程支持,您会很自然地问,为什么C++没有提供,答案是因为效率、控制以及C++适用的应用程序的范围。由于没有内建对多线程的支持,因此C++没有尝试定义一种“万能的”解决方案。相反,C++允许您直接使用操作系统提供的多线程特性。这种方法意味着您的程序可以使用执行环境支持的、最高效的方法来实现多线程。由于许多的多任务环境提供了对多线程丰富的支持,因此能够访问这些支持对于创建高性能的多线程程序至关重要。
Windows下,它提供了多组线程相关函数来有条理地控制线程的创建和管理。例如,Windows有多种方法来控制对共享资源的访问,共享资源包括信号、互斥体、事件对象、可等待定时器以及临界区。由于操作系统能力的不同,很难将这种灵活性设计到一门语言中。因此,对于多线程语言层次的支持通常意味着仅提供特性的“最小公倍数”。通过C++,您可以访问操作系统提供的所有特性。当编写高性能的代码时,这是非常重要的优点。