《Win32多线程程序设计》读书笔记(2)

来源:互联网 发布:丰臣秀吉 知乎 编辑:程序博客网 时间:2024/05/12 21:15

学习完成本章,要回答一个问题,为什么要使用线程?

1. 并不是每一个程序都必须使用线程,但多线程多任务,将使得多媒体软件或Internet软件的效率大大提高。

2. 单线程程序就象超级市场中唯一的一位出纳员,对于小量采购可以应付自如,但如果有人采购了一大车货品,结账就需要点时间,而其它人都必须等待;

此时,多线程程序就像有一群出纳员,每个人负责一条线。一条线瘫痪了,也不会影响其它线。(Nice comparison)

3. 定义:多线程能使程序将其工作得以分开,独立动作,不互相影响。

一个小故事:微软在20世纪80年代中期,曾经卖过一个Unix版本,名为XENIX。在OS/2和WindowsNT推出的前几年,XENIX就有了抢先式多任务,但与DOS十分不相容,不容易学习和维护,所以淡出了市场。但是,似乎XENIX又回来了。。。

4. 为什么用户需要多线程多任务?

一个例子,当使用Windows NT 3.x 的文件管理器(File manager)连接 一个忙碌服务器时,整个窗口就不动了。

5. Win32基础之线程和进程?

从Win32角度来看,进程含有内存和资源。被进程拥有的资源,理论上可达2G。资源包括核心对象(如文件句柄和线程)、USER资源(如对话框和字符串)、GDI资源(如Device Context和Brushs)。

进程就像一本活页笔记夹,你可以在其中的活页上写东西,也可以擦掉内容或整页撕掉,活页笔记夹只是持有这些东西而已。同理,进程本身并不能执行,它只是提供一个安置内存和线程的地方。(Great Comparison)。

注意:在Unix中,进程与其主线程是相同的东西。

内存就像前面所说的活页夹中的活页纸,它代表的意义完全由纸上的内容而定,大致可以分为三类:

代码Code:程序的可执行部分,为只读部分,是CPU唯一允许执行的内存。

数据Data:是程序中的所有变量(不包括函数中的局部变量),可以区分为全局变量和静态变量两种。线程中也可以使用malloc和new动态配置内存。

堆栈Stack:调用函数时所用到的堆栈空间,其中包括局部变量。每个线程产生时配一个堆栈。

在上面,进程和内存并没有真正做什么事情,一旦CPU开始执行程序代码,就得有一个“线程”。定义一个线程,需要的数据并不多。线程的”状态”被记录在进程的“活页上”,或者CPU的寄存器中。

6. 为什么要使用线程?或者说什么是线程能做的而多进程(Mutli-processes)没有的?

一个重要的理由就是线程的“价廉”。线程的启动和退出都快,对资源的冲击比较小。 下面是几个例子,用来比较进程和多线程:

a) 多进程中,如何将窗口的Handle交给另一个进程。Win32中,Handle只在产生的进程中才有意义,这样可以避免危及另一个进程的资源。为了分享Handle,必须明明白白产生一个handle的副本,并传递给另外一个进程。而线程则不用,所有线程可以共享同一进程中的资源。

b) 在服务器中,同一个服务软件可能同时服务成千上万上客户端,而Web服务器又是“stateless”的,即无状态的,换句话说,每一个用户的请求都是相互独立的,并且往往只带少量数据。此时,可能需要为每一个请求产生一个新的进程。这样做的负载(Overhead)是非常大。

c) 在Server/Client环境中,存在着所谓的工作组数据库服务器。可能会一些用户对它产生的连接(Connection)持续数小时之久。 这个时候的负载不大,但是多个进程共享一个数据库,就要设置共享的跨越进程的数据结构,使问题复杂化。

7. 线程的上下文切换(Context Switching)

此时CPU取得当前线程的状态后,即把所有寄存器内容拷贝到堆栈中,再把它从堆栈中拷贝以一个Context结构中,以备以后使用。更具体一点,上下文切换,即是要换一套Memory Context,包括Page Directory和Page Tables。

8. CPU越多,则多个线程都可以运行,不需要Context Switch。

Windows NT以其Symmetric Multi-Processing(SMP)技术支持多个CPU机器。每一个CPU执行一个不同的线程。一个双CPU系统可以同时执行同一进程(或不同进程)的两个线程。

线程的切换存在着一个问题,就是竟争条件(Race Conditions)。这种情况发生在多个线程同时操作一个数据结构,如链表时,其跟我们多个用户同时去操作数据库中同一表的同一记录情况时相似,也存在着结果的不确定性。在数据库中,我们是定义原子操作去控制这种“脏数据”的,在线程中也一样,可以定义原子操作(Atomic Operations)。

9. 原子操作

上面已经讲过,可以利用原子操作来阻塞竟争条件带来的不利影响。但是一个关键因素就是如何鉴定Race发生的地点。在这里,该书列举了一个非常好的例子,讲解关于原子操作控制的时间P20。

10. 使用线程的难点?

线程间的通信、竞争控制。

最后一个问题,是不是线程越多越好???

作者的一个形象比喻,在厨房里面,并不是人越多越好,有时候额外的协助反而带来更多的麻烦。

原创粉丝点击