1、进程、线程、服务和任务的区别
进程(process),是指运行中的应用程序,每一个进程都有自己独立的内存空间。一个应用程序可以同时启动多个进程。例如对于IE浏览器程序,每打开一个IE浏览器窗口,就启动了一个新的进程。同样,每次执行JDK的java.exe程序,就启动了一个独立的Java虚拟机进程,该进程的任务是解析并执行Java程序代码。
线程(thread),是操作系统能够进行运算的最小单位。线程被包含在进程之中,是行程中的实际运行单位。一条线程是指进程中的一个单一顺序的控制流,一个进程中可以并行多个线程,每条线程并行执行不同的任务。当进程内的多个线程同时运行时,这种运行方式称为并发运行。许多服务器程序,如数据库服务器和Web服务器,都支持并发运行,这些服务器能同时响应来自不同客户的请求。
进程和线程的主要区别在于:每个进程都需要操作系统为其分配独立的内存地址空间,而同一进程中的所有线程在同一块地址空间中工作,这些线程可以共享同一块内存和系统资源,比如共享一个对象或者共享已经打开的一个文件。
服务(service),也称为守护线程,是没有界面的,默默运行在系统后台的。他可以为应用程序提供一些更有特色的东西,比如播放MP3,开启一个播放MP3的服务,用户点击开始按钮通知服务开启,点击关闭按钮通知服务关闭,如果你禁用这个服务,那别人想播放MP3那是不行的,而且服务之间是有可能互相依靠的。
任务(task),是指由软件完成的一个活动。任务是比较抽象的概念,是一个一般性的术语,一个任务既可以是一个进程,也可以是一个线程。简而言之,它指的是一系列共同达到某一目的的操作。例如,读取数据并将数据放入内存中。这个任务可以作为一个进程来实现,也可以作为一个线程(或作为一个中断任务)来实现。
2、多线程(multithreading)与超线程(Hyper-Threading)
在讲多线程之前,需要知道什么是同步、什么是异步。简单的说,同步就是要两端按照同一个频率来进行消息处理,异步就是两端按自己的频率来进行消息处理。我们略去底层硬件定义的那种晦涩的解释方式,用比较通俗的语言来解释下:
同步:发送方发出数据后,等接收方发回响应以后才发下一个数据包的通讯方式;
异步:发送方发出数据后,不等接收方发回响应,接着发送下个数据包的通讯方式。
下面我们讲一下多线程。假设现在有一个CPU,运行两个线程,那么这两个线程其实不是并行运行的,在微观的CPU内部里面,还是串行处理的。CPU通过线程中断,让某一个线程挂起来,然后切换到另一个线程,执行一会儿,再切换回来,使得宏观上看上去好像两个线程同时运行一样。线程切换肯定会带来一定的性能牺牲,于是我们可以增加CPU,这样就真正的做到微观上面的线程并行了,然而线程数大于物理CPU核数后肯定会带来线程切换带来的性能影响,那为何要用多线程呢?
计算机最重要的部位就是CPU,只有当CPU充分利用的时候,计算机的威力才会被发挥回来,因此我们的目的就是提高CPU的利用率,不让其空闲。
假设我们现在运行的任何程序都是纯异步的,也就是说没有存在任何的等待时间,换一句话说CPU从来不会空闲起来,此时的线程数如果大于物理CPU个数的话将会得不偿失,因为线程切换回带来一定的性能开销。
然而不幸的是,现实总是那么的残酷,世界到处存在等待的时间,CPU也不例外。想想看买票都需要排队等待呢,换句专业的术语就是“同步”。那我们想想为啥我们现实生活中会发生等待现象呢?因为资源单一,试想一下,如果我们每个人都有票了,那还排啥队啊,为啥买票,票不在我们手里呗;为啥排队,售票点就那么几个,人又那么多,无规矩不成方圆呗。
计算机里面同样也是这样的情况,就那么几个硬件,比如我就一个硬盘,可是四个CPU来访问,这时候CPU多有啥用,你还是得等待,不等待就跟你买票付了钱,人家突然冲过来把票抢走了,什么素质啊。这就是互斥锁存在的意义了,访问共享资源的时候要锁住线程,不能让其他人来抢劫。别人就只能等待了。
等待意味着什么,意味着你只能想办法浪费时间了,睡觉也好,打游戏也好,听音乐也好。如果这个线程等待了,就相当于它去睡觉了,那如果此时CPU只有一个线程呢?这个线程等待的时候, CPU就空闲着了。这就是多线程存在的意义了,在大多数存在同步等待情况的程序中,线程数如果大于物理CPU个数的时候,是可以充分利用CPU,提高性能的。但无限制的加大线程数会带来线程切换的开销,所以一个服务程序的最优线程数需要根据具体情况来具体评估。幸运的是,大部分的服务都是存在同步情况的,于是多线程就显得非常有用处了。
那超线程什么呢。我们回顾一下多线程概念,电脑在执行命令的时候会锁定了下个将被执行的指令的内存储存位置,使CPU精确地知道从哪儿得到这些指令。当一个线程发送到CPU,这线程的内存地址就被锁定,所以CPU明白从哪里开始执行线程。电脑能够递增处理每个指令,一直到处理完一个线程为止。在线程执行以后,电脑就会重新读入下个要执行的指令位置。不同线程可以彼此相互中断,即强迫CPU把电脑上当前处理的结算结果储存在栈里。而这样造成的缺陷就是CPU每次只能处理一个线程。而超线程技术呢?就是让一个CPU可以每次执行一条以上来自不同线程的技术,这样可以减少很大部分的多线程切换操作。不同于提高CPU的时钟速度和增加缓存容量等物理手段,超线程技术可以让系统误以为系统内有两块物理CPU,操作系统就会同时向那‘两’块CPU发送2个线程的任务。在带有超线程技术的CPU上, CPU将会尝试同时执行两个线程(两个线程使用一个cpu上的不同执行单元),因此解决了CPU执行单元利用率低下的问题。不过,如果线程的数目小于物理CPU核数的话,那么其实有无开启超线程其实并没有多大的区别。只有当开启的线程数目大于CPU核数的情况下其优势可能才会体现出来,然而这样的情况也只是在多线程比单线程更适合的程序才可以,即大量的同步通信的程序上其多线程的效果才会可能体现出来。这时候开启超线程有可能会带来收益,而且这些线程的功能点重合越少,效果越明显。而一般的商业网络服务器都存在网络交互的情况,因此超线程可能可以带来一定的提升,然而还是有可能会带来零收益、甚至反作用的,所以需要经过严格的评估测试后再进行决策。