第二章多线程分布式计算课后答案
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
第二章
1. 选择题
12345678910
D A B C C
E C A B B 1112131415161718
B B B
C A
D A A
2. 程序/方法与进程/线程有什么不同?(53页第四段)
答:一个程序/方法是由程序员写的一段代码,它是静态的。
进程/线程是由执行的程序/方法、当前值、状态信息和用于支持它执行的资源构成,资源是它执行时的动态因素。
换言之,一个进程/线程是一个动态实体,只有当程序或函数执行时才会存在。
3. 比较多进程(多任务)操作系统和多线程编程环境。
(53页5、
6、7段)
答:为了真正并行执行多个进程/线程,必须存在多个处理器。
如果系统中只有一个处理器,表面上多个进程/线程执行,实际上实在分时模式下顺序执行。
从同一代码块可以创建多个进程/线程。
默认情况下,包含在不同进程/线程中的代码和数据是分离的,每一个都有它自己执行代码的副本、局部变量的栈、对象数据区以及其他数据元素。
通常情况下,一个分布式操作系统可以由不同电脑上的多个实例或副本构成,每一个实例或副本都可以管理多个进程。
同样,每个进程可以是由多个线程组成的一个多线程程序。
4. 什么是临界操作?用什么方法可以来保护临界操作?(54页第1
段)
答:对共享资源的访问称为临界操作。
虽然一个简单的锁定可以防止共享资源被访问,但是也消除了并行处理的可能性。
更理想的方法是不锁定并行读操作,而锁定并行读-写和写-写组合。
5. 什么是死锁?哪些策略可以用来解决死锁问题?(55页)
答:死锁的情况是两个或多个竞争操作等待对方完成,导致都不能完成。
解决方法:
(1) 死锁预防:使用一种算法可以保证不会发生死锁。
(2) 死锁避免:使用一种算法,能够遇见死锁的发生从而拒绝资源请求、
(3) 死锁检测和恢复:用一种算法来检测死锁的发生,强迫线程释放资源、挂起等待。
6. 改进哲学家就餐问题使其不会产生死锁?
答:每一次最多只能有4个哲学家(共有5个哲学家)申请就餐,这样其中的一个哲学家就能申请到两只筷子,就能够进餐,再将筷子释放给其他哲学家就餐,直到所有哲学家就餐完毕。
7. Java中睡眠使用:sleep()方法;等待使用wait()方法;挂
起使用join()方法。
l sleep()
调用sleep()方法使线程暂时停止一段执行时间,该时间由给定的毫秒数决定 ,线程在指定时间内不会运行,会自动唤醒,不会让出控制权。
l join()
方法使线程挂起,使当前执行的线程停下来等待,直至join()方法所调用的那个线程结束,再恢复执行 。
例如:当有a和b两个线程,启用b.join();方法时,a线程就会被挂起,直到b线程结束,a线程才继续执行。
l wait()
使线程等待,直到线程得到了notify()和notifyAll()消息,线程才会进入“可执行”状态。
wait()、notify()、notifyAll()不同于其他线程方法,这3个方法是ng.Object类的一部分,所以在定义自己类时会继承下来。
8. 创建子进程:int fork();
启动子进程:exec(参数列表);
9. 在java中,几个线程方法wait(),notify(),
notifyALL()用于协调对共享资源的访问。
C#的Monitor类具
有执行相同功能的方法,它们是
Monitor.Wait(),Monitor.Pulse(),Monitor.PulseALL()。
完全等价的有:start();run()。
独有的是:sleep()方法。
10. C#和java启动线程是一样的,都使用:Thread.Start()方
法。
C#中创建线程:Thread t = new Thread(new
ThreadStart(FunctionName));
java中创建线程:
方法一:继承Thread类创建线程
(1)继承Thread类;
(2)覆盖run()方法;
(3)用new MyThread(...)创建一个线程
(4)通过调用start()方法启动线程
方法二:实现Runnable接口创建线程
(1)实现Runnable接口;
(2)覆盖run()方法;
(3)用new MyThread(...)创建一个线程
(5)通过调用start()方法启动线程
11. 解释monitor是怎么实现的?为什么
monitor.enter/monitor.exit不能通过自动装箱拆箱的方式获
得值类型变量?(P79)
答:
(1) 在进入一个buffer对象引用之前,运行时环境检查锁的开关状态。
如果锁是开的(true),线程告诉Monitor.Enter阻塞。
堆内存中的对象锁被存储在叫做同步阻塞的表中;如果锁是关的(false),线程告诉Monitor.Enter解锁。
在访问缓冲区引用的对象时阻止其它线程进入。
(2) 如果monitor.enter/monitor.exit通过自动装箱拆箱的方式获得值类型变量,可能会出现语义错误。
12. 为什么C#中的reader/writer锁比Monitor锁更有效率?(P84)答:ReaderWriterLock类允许读-读重叠,而Monitor类阻止任何重叠;
ReaderWriterLock类的锁定方法有一个超时的参数,指定放弃前等待多长时间。
而如果对象被锁定,Monitor.Enter永远等待,
Monitor.TryEnter立刻放弃。
13. 当线程正在执行被锁操作保护的代码时,是否可以中断?(从
执行状态转换到就绪状态)?为什么?
答:不能。
因为被加锁的代码段就是一段互斥段,互斥段在一个时刻内只允许一个线程进入执行,其它线程必须等待。
14. 如何通过同步/监视机制保护共享对象?
(1) lock 关键字将语句块标记为临界区,方法是获取给定对象的互斥锁,执行语句,然后释放该锁。
lock 确保当一个线程位
于代码的临界区时,另一个线程不进入临界区。
如果其他线
程试图进入锁定的代码,则它将一直等待(即被阻止),直
到该对象被释放
(2) 与 lock 关键字类似,监视器防止多个线程同时执行代码块。
Enter 方法允许一个且仅一个线程继续执行后面的语
句;其他所有线程都将被阻止,直到执行语句的线程调用
Exit。
这与使用 lock 关键字一样。
事实上,lock 关键字就
是用 Monitor 类来实现的
15. 什么是事件?事件与锁之间的主要区别是什么?
AutoResetEvent与ManualResetEvent之间的区别是什么?(P86
和P87)
答:在C#中,事件是某一受关注的事件发生后的通知,每一个事件包含了关于这一特定事件的信息。
16. 异常处理与事件驱动编程的主要区别是什么?
答:异常处理用于处理计算过程中发生的异常情况,是用来处理非正常情况的;而基于事件驱动的编程时用于处理特殊的令人关注的事件,比如单击鼠标。
17. 基于控制流的编程与事件编程的主要区别是什么?(P95)答:控制流驱动方法有唯一的程序入口,输入数据来自不同时间不同地点,只有当控制流返回这一地点时输入数据才被处理;在基于事件驱动的方法中,提供了事件板和报警板机制,事件板记录少量的紧迫请求,报警板负责更加迫切的请求。
在事件驱动中,方法作为事件处理,而不是控制流的一部分。
18. 代理与类有什么不同?(P96)
答:代理是类型安全的,不执行隐式类型转换。
(1) 代理允许方法名作为参数……
(2) 通过把事件处理的名字……
19. 代理与方法有什么不同?
答:代理声明定义了一个引用类型,它可以封装一个带有特定签名的方法。
代理类似于C++中的函数指针。
方法是一个可以被其它程序调用或者重用的代码块,方法通过名字、参数列表和返回类型来定义,编程时,方法作为程序的一个构件和控制流的一部分。