table {
border-collapse: collapse;
width: 100%;
margin-bottom: 1rem;
}
th, td {
border: 1px solid #ddd;
padding: 8px;
text-align: left;
}
th {
background-color: #f2f2f2;
}
tr:nth-child(even) {
background-color: #f9f9f9;
}
pre {
background-color: #f8f8f8;
padding: 15px;
border-radius: 4px;
overflow-x: auto;
}
46、练习1:理解“丢失更新”问题(第1部分:基本问题) – 值应从1000开始,最终变为2000。此说法是否正确?
若进行一千次增量更新,从1000开始,最终会变为2000,所以此说法正确。
47、练习1:理解“丢失更新”问题(第1部分:基本问题) – 当前值应为2000,最终应变为1000。请解释最终值变为1000的原因。
可能是在执行了一定数量的递增和递减操作后达到此结果,如从 2000 开始,进行了 1000 次递减操作后,值会变为 1000。
48、练习1:理解更新丢失问题(第一部分:根本问题)——由于对数据值没有重叠访问,因此不会发生数据损坏。
此说法正确。当对数据值没有重叠访问时,一个进程的操作不会干扰另一个进程的操作,不会出现一个进程覆盖另一个进程更新的情况,所以不会发生数据损坏。
49、练习1:理解“丢失更新”问题(第一部分:基本问题)——给定初始值为1000,进行一千次增量更新和一千次减量更新,最终值应该是多少?
在给定初始值为1000,进行一千次
增量更新
和一千次
减量更新
的情况下,最终值确实应该是1000。
因为
增量
和
减量
的次数相同,相互抵消,所以结果会回到初始值。
50、练习1:理解更新丢失问题(第一部分:根本问题)——对数据变量的无监管重叠访问会导致更新丢失,系统变得不一致。
该描述正确。当对数据变量进行无监管的重叠访问时,可能出现一个进程覆盖另一个进程更新的情况,即更新丢失,进而使系统数据不一致。
例如在两个线程对共享变量进行操作的场景中,若访问重叠,一个线程的更新可能被另一个线程覆盖;在银行系统和航空公司订票系统的例子里,也会因无监管的重叠访问导致资金损失或座位数据不一致等问题。
51、练习2:理解“丢失更新”问题(第二部分:探究问题的本质)——数据库应用中的事务需要相互隔离。必须对事务外部的进程隐藏部分结果,以防止系统变得不一致。这种说法是否正确?
此描述正确,事务相互隔离并隐藏部分结果可避免系统因数据不一致而出现问题,如丢失更新问题,可通过事务机制确保资源一致性。
52、在线航班预订系统和仓库库存管理系统分别可能出现哪些问题?
- 在线航班预订系统存在超额预订或显示无座但实际有座的情况;
- 仓库库存管理系统存在实际库存与系统显示数量不一致的问题。
53、以下哪些系统易受更新丢失问题影响:网上银行、股票交易、网上购物和电子商务,判断该说法是否正确,并说明理由。
该说法正确。更新丢失问题指一个进程使用变量的过期值进行计算并写回新的错误值,导致系统数据不一致。
例如在网上银行中,两个线程(如存款和取款操作)更新共享变量(账户余额)时,若访问重叠,可能出现一个操作覆盖另一个操作更新的情况,造成数据不一致。
股票交易、网上购物和电子商务系统也存在类似多线程并发操作共享数据的情况,所以也易受更新丢失问题影响。
54、请解释为什么差异是随机的
差异是随机的,原因在于线程执行时间对低级调度器决策序列高度敏感,而该序列会根据精确的系统条件在每次运行时有所不同,且这种差异不可预测,可能更严重。
55、为什么线程执行结果会产生差异?
线程执行结果出现差异的原因在于其执行时间易受低级调度器决策序列影响,而这些决策会因每次运行时的具体系统条件不同而发生变化。
56、为什么说差异不可预测会更严重?
该陈述指出差异不可预测,意味着难以提前知晓其出现的时间、程度和影响范围,所以潜在危害更大,可能会给系统带来更严重的问题。
57、练习3:理解“丢失更新”问题(第3部分:锁的必要性) – 锁机制可防止对资源的重叠访问。判断该说法是否正确。
这句话是正确的,锁机制的作用之一就是避免多个线程或进程同时对同一资源进行访问,防止出现重叠访问的情况,从而保障数据的一致性和正确性。
58、练习3:理解“更新丢失”问题(第三部分:锁的必要性)——锁必须应用于两个线程。
该说法正确,锁必须应用于两个线程,以防止对资源的重叠访问,从而避免更新丢失问题。
59、练习3:理解“丢失更新”问题(第3部分:锁的必要性)——在应用锁时,必须防止外部进程的读写操作。为什么要这样做?
在应用锁时,要防止外部进程进行读写操作,以保证资源的访问不会出现混乱,避免丢失更新问题。
60、练习3:理解“丢失更新”问题(第三部分:锁的必要性)——锁应在事务的读取阶段之前应用。这句话对吗?
该表述是正确的。在处理事务时,为避免丢失更新问题,需要在读取数据之前就对资源加锁,以保证在该事务处理过程中,其他进程无法对资源进行重叠访问,确保数据的一致性和准确性。
61、练习3:理解“丢失更新”问题(第3部分:锁的必要性)——锁应该在事务的写入阶段之后释放,这种说法是否正确?
这种说法是正确的。锁在事务的写入阶段之后释放,能保证数据完整性和一致性,避免丢失更新问题。因为在写入阶段之后释放锁,能确保在写入数据的过程中,没有其他线程或进程对该资源进行访问和修改,从而保证事务的原子性和隔离性。
62、练习3:理解“丢失更新”问题(第3部分:锁的必要性) – 这句话意味着锁能确保同一时间只有一个进程可以访问资源。判断该说法是否正确。
这句话准确描述了锁在解决“丢失更新”问题中的作用,通过确保
同一时间只有一个进程访问资源
,避免了多个进程对共享资源的
并发访问导致的数据不一致
,从而防止
丢失更新问题
的发生。所以该说法正确。
63、练习3:理解“丢失更新”问题(第三部分:锁的必要性)——该陈述意味着,通过一次只允许一个进程访问资源,丢失更新问题就不会发生。
该陈述是正确的。一次只允许一个进程访问资源,可避免多个进程对资源的重叠访问,从而防止一个进程覆盖另一个进程的更新,避免丢失更新问题。
64、练习4:探究死锁问题 – 线程请求事务所需的资源用红色箭头表示,一旦资源空闲,线程将被授予对该资源的访问权限,并在事务执行期间持有该资源,这一过程用蓝色箭头表示。请说明这种表示方式对于分析死锁情况有什么作用。
该描述说明了线程在资源请求和使用过程中的状态变化。线程发出请求时用红色箭头表示,获得资源并使用时用蓝色箭头表示,这有助于观察和分析死锁情况,因为死锁往往与资源的请求和持有状态相关。
65、以下关于死锁问题的描述,正确的是:a. 死锁应该不可能发生。b. 如果每个事务中至少使用两个资源(例如,如果事务各自访问数据库中的两条或更多记录),则可能发生死锁。c. 如果在表级别进行锁定且不使用其他资源,则不会发生死锁,但一个进程必须等待另一个进程使用完资源。如果使用行级锁定且每个进程访问不同的记录集,则死锁应该不可能发生。d. 如果访问模式完全是只读的,则不需要锁定,在这种情况下不会发生死锁。
- **b选项正确**。当每个事务中至少使用两个资源时,事务之间可能会因为资源的循环等待而导致死锁,所以可能发生死锁;
- **a选项错误**,在一定条件下死锁是可能发生的;
- **c选项中使用行级锁定时**,即使每个进程访问不同的记录集,也不能绝对保证死锁不可能发生;
- **d选项错误**,虽然访问模式完全是只读在很多情况下不需要锁定,但在一些特殊的并发控制场景下,可能还是会有锁定需求,也不能绝对说不会发生死锁。
66、练习5:探索虚拟内存和页面置换算法的基础知识 – 一个合适的性能指标是在使用每种页面置换算法时发生的页面错误数量。判断该说法是否正确。
这句话是合理的。页面错误数量能反映页面置换算法的性能,数量越少,算法在预测哪些页面会被再次使用并将其保留在物理内存方面表现越好,能更好地满足应用程序的内存需求,减少因页面不在物理内存而需从磁盘交换进来的情况。
67、练习5:探索虚拟内存和页面置换算法的基础 – 若模拟一个具有良好空间局部性、反复访问一小部分内存页面的应用程序,那么LFU或LRU页面置换算法的性能是否会比随机算法或FIFO算法更好?
该描述正确。具有良好空间局部性且反复访问小部分内存页面的应用场景下:
LRU算法
基于进程内存引用的空间局部性,能将近期引用的页面保留在物理内存中;
LFU算法
通过记录页面引用次数,也能在一定程度上选出合适页面进行置换。
而:
随机算法
不考虑页面使用情况;
FIFO算法
不依据页面使用情况选择置换页面;
所以
LFU和LRU算法性能通常更好
。
68、指出以下软件架构的主要优点和缺点:(a) 客户端 – 服务器 (b) 点对点 (c) 三层 (d) 多层 (e) 分布式对象
架构优缺点分析
优点
(a)
客户端 – 服务器架构
在小规模或低复杂度应用中表现良好,两种组件功能不同,理解度高。
(b)
点对点应用
动态运行时配置灵活,可临时连接多个组件实现数据或资源共享。
(c)
三层架构
可分离用户界面、业务逻辑和数据访问逻辑,更灵活、可扩展和健壮。
(d)
多层架构
是三层架构的扩展,进一步细分业务逻辑,增加灵活性和可扩展性。
(e)
分布式对象方法
在对象级别分布应用逻辑,灵活性高。
缺点
(a)
客户端 – 服务器架构
性能和可扩展性受功能划分方式影响。
(b)
点对点应用
连接可能成为性能瓶颈,影响可扩展性。
(c)
三层架构
比两层客户端 – 服务器架构更复杂,需要更多设计和测试工作。
(d)
多层架构
增加了系统的复杂性。
(e)
分布式对象应用
可能存在高复杂性,设计不佳会有大量组件依赖和高交互强度,影响健壮性,且依赖中间件等支持基础设施。
69、组件耦合。识别以下每种场景中发生的耦合类型:(a) 在中间件上运行的客户端 – 服务器(CS)应用程序;(b) 使用硬编码地址来识别组件位置的原型三层系统;(c) 组件使用目录服务来查找其他组件地址的多层应用程序;(d) 组件在本地网络中被发现时相互连接的对等(peer – to – peer)应用程序(发现过程是自动的,基于广播消息的使用);(e) 客户端连接到在线服务以交换信息的社交媒体应用程序;(f) 使用服务器广告广播使客户端能够定位服务器并建立连接的 CS 应用程序。
(a) 在中间件上运行的 CS 应用程序:通过中间件间接传递消息实现组件连接,属于松散耦合。
(b) 使用硬编码地址识别组件位置的原型三层系统:硬编码地址决定组件连接,属于紧密耦合。
(c) 组件使用目录服务查找其他组件地址的多层应用程序:组件通过目录服务获取地址进行连接,属于松散耦合。
(d) 基于广播消息自动发现并连接的对等应用程序:组件动态发现和连接,属于松散耦合。
(e) 客户端连接在线服务交换信息的社交媒体应用程序:客户端与在线服务连接,客户端间无直接耦合,属于松散耦合。
(f) 使用服务器广告广播建立连接的 CS 应用程序:客户端通过广播定位服务器连接,属于松散耦合。
70、识别异构性。确定以下每种场景中可能出现的异构性类别:(a) 一个计算机实验室,计算机在两年内分批购买,所有计算机都安装了Windows操作系统和相同的应用程序套件。(b) 一个小公司网络系统,包括几台运行不同版本Windows操作系统的台式计算机和几台同样运行Windows操作系统的笔记本电脑。(c) 一个支持CS业务应用的系统。一台运行Linux操作系统的强大计算机用于托管服务器进程。用户通过运行Windows操作系统的低成本台式计算机访问服务。(d) 一群朋友通过无线链接在包括智能手机和平板电脑在内的移动设备上玩多人游戏时创建的临时网络。(e) 一个家庭网络系统,包括一台运行Linux操作系统的台式计算机、一台运行Windows操作系统的笔记本电脑和一台运行Mac OS X操作系统的笔记本电脑。
(a)
性能异构性
。由于计算机是在两年内分批购买的,不同批次计算机的资源配置可能不同,如处理器速度、内存大小、磁盘大小等,从而导致性能差异。
(b)
性能异构性和操作系统异构性
。不同台式机和笔记本电脑可能存在资源配置差异,导致性能异构;同时运行不同版本的Windows操作系统,存在操作系统异构。
(c)
平台异构性和操作系统异构性
。用于托管服务器进程的计算机和用户访问服务的计算机性能不同,可能存在平台异构;且分别运行Linux和Windows操作系统,存在操作系统异构。
(d)
平台异构性和性能异构性
。智能手机和平板电脑的底层平台、硬件设施等不同,存在平台异构;不同设备的资源配置不同,会导致性能异构。
(e)
操作系统异构性
。系统中包含运行Linux、Windows和Mac OS X三种不同操作系统的计算机,存在操作系统异构。
71、编程练习 #A1:实现自动配置,使应用程序服务器组件能够检测并自动连接到数据库服务器。推荐的实现方法是在数据库服务器中添加服务广告机制。
需在数据库服务器中添加服务广告机制,实现应用程序服务器组件检测并自动连接到数据库服务器的自动配置。
72、编程练习 #A2:实现自动配置,使应用程序客户端组件能够检测并自动连接到应用程序服务器。推荐的实现方法是在应用程序服务器中添加服务广告机制。
需在应用程序服务器添加服务广告机制,实现应用程序客户端组件自动检测并连接到应用程序服务器。
73、编程练习:有一个对等网络媒体共享应用程序,它能自动发现对等节点并显示它们拥有的额外资源,使用户无论哪个对等节点持有音乐,都能播放音轨。但该应用程序无法检测对等节点的断开连接,导致实际的音乐曲目可用性列表可能过时。现在需要扩展该对等网络应用程序的功能来纠正这种情况。从给定的项目和源代码开始,添加一个简单的心跳检测机制,让每个对等节点可以监控它已经检测到的其他对等节点是否仍然存在。已知对等节点会定期生成自我广告消息,但目前接收方一旦发现某个发送方,就会忽略该发送方的这些消息。可以修改接收逻辑,利用这些消息来检查对等节点是否仍然存在。如果在一段时间内未检测到某个对等节点,则假定它不再存在,本地对等节点必须停止宣传该丢失对等节点持有的资源。在确定一个对等节点已离开之前等待的时间方面,连续错过三条自我广告消息是合适的,不过你也可以尝试其他配置。有原始版本、重构版本或库版本三个版本的示例代码可用,你可以使用任意一个版本作为起点。
项目任务说明
从给定的项目和源代码开始,为对等网络应用程序添加简单的心跳检测机制。
具体要求
修改接收逻辑,利用对等节点定期生成的自我广告消息来检查其是否仍然存在。
若连续错过三条自我广告消息,假定该对等节点不再存在。
本地对等节点应停止宣传其持有的资源。
可选起点
原始版本示例代码
重构版本示例代码
库版本示例代码
74、编程练习 #A4:有一个演示复制数据库应用程序,目前仅支持增量更新传播,即主实例发生的每次更新都会逐个传播到备份实例。但这存在一个潜在弱点,若备份服务器在一段时间内不可用(崩溃或关闭)然后重新启动,它可能会错过一些更新。现在需要实现一个全数据库传输机制,要求开发一种机制,使备份服务器实例在启动时向主服务器实例请求全数据库传输。需要添加一种新的消息类型 REQUEST_FULL_DATABASE_TRANSFER,以使备份实例能够发出请求,并且可以使用现有的更新传播机制(在循环中)逐行传输数据库。
数据库传输机制改进方案
需要为演示复制数据库应用程序实现全数据库传输机制。
当前应用仅支持增量更新传播,存在备份服务器重启可能错过更新的问题。
为解决此问题,应开发如下机制:
机制描述
:备份服务器启动时向主服务器请求全数据库传输
实现方式
:
添加消息类型:
REQUEST_FULL_DATABASE_TRANSFER
利用现有更新传播机制逐行传输数据库
75、在一个系统中,每个组件大约与其他一半的组件进行交互,该系统的交互复杂度级别是多少?
O(N²/2)
76、计算发生的独立交互数量的公式是什么?
在每个组件与大约一半其他组件交互的系统中,公式为 $ N imes N / 4 $;
在每个组件与大约四个其他组件交互的系统中,公式为 $ 2N $。
其中 $ N $ 为系统中的组件数量。
77、如果系统中有10个组件,会发生多少次单独交互?
在系统中每个组件与大约一半其他组件交互的情况下,有
25次单独交互
;在系统中每个组件与大约四个其他组件交互的情况下,有
20次单独交互
。
78、IDL 是如何促进实现透明性的?
IDL 将程序代码的接口部分与实现部分分离,有助于通过中间件服务自动处理与接口相关的方面,如连接和通信功能。应用开发者可专注于应用行为的业务逻辑方面(即实现),隐藏了组件实现方式的细节,从而促进实现透明性。
79、为什么接口定义语言(IDL)只包含接口定义而不包含实现细节?
应用逻辑的实现包含在组件内部,不暴露在接口中,调用组件只需接口定义中的信息来调用方法,不需要实现细节,所以 IDL 不需要表示实现,也没有表示实现的语言结构。
80、在促进对共享资源的并发访问时,主要挑战是什么?
主要挑战是维护一致性。必须确保在所有可能的使用场景下,数据资源保持一致,无论出现何种访问或更新序列,系统都应实施必要的控制,以保证数据的所有副本都正确且反映相同的值。
81、事务如何有助于并发透明性?
事务
是相关操作的不可分割序列,必须完整处理或中止,且不改变系统状态。
原子性
:确保操作要么全部执行,要么都不执行。
一致性
:保证系统存储数据在事务结束时处于一致状态。
隔离性
:要求事务间无干扰,通过锁定资源和使用互斥机制来实现。
持久性
:使事务结果永久存储。
这些特性确保资源共享时数据值的一致性,防止因无监管的交错访问导致数据损坏,从而有助于实现并发透明性。
82、名称服务是如何有助于实现位置透明性的?
名称服务维护着一个包含服务及其位置的数据库。当组件A需要查找组件B的地址时,它会向名称服务发送请求,并提供组件B的名称作为参数,名称服务会以组件B的地址详情作为回复。
这种方式将位置查找的工作交由用户应用程序外部处理,并通过服务注册等技术保持更新,使得用户无需了解资源的具体位置就能访问,从而实现了
位置透明性
。
83、实施复制时的主要挑战是什么?
实施复制时的主要挑战是维护一致性。每个资源副本必须保持相同的值,一个副本更新时,其他副本也必须更新,以确保无论读取哪个副本,应用程序都能获得相同的值。
84、两阶段提交协议如何有助于实现健壮的复制机制?
两阶段提交协议确保数据资源的所有副本实例都执行更新操作,或者都不执行,从而保持一致性,有助于实现健壮的复制机制。
85、修改用例游戏的客户端和服务器组件,使服务器可以在目录服务中注册,客户端随后可以使用目录服务获取游戏服务器的 IP 地址和端口详细信息。对于服务器端,需要考虑游戏服务器在何时向名称服务注册,最好在游戏服务器初始化时自动完成。对于客户端,有两种方法:可以在客户端用户界面设置一个“联系目录服务”按钮;或者更透明的方法是,在游戏客户端启动时自动联系目录服务。
服务器端应在游戏服务器初始化时自动向目录服务注册,注册消息编码为包含 `REGISTER:server_name:port` 的字符串,其中服务器名称最长 30 个字符,端口号以文本形式表示。
客户端可以通过两种方式联系目录服务:
1. 在客户端用户界面设置“联系目录服务”按钮
2. 在游戏客户端启动时自动联系
客户端的 RESOLVE 请求消息编码为包含 `RESOLVE:server_name` 的字符串,服务器名称最长 30 个字符。
目录服务使用 UDP 协议:
- 客户端监听端口为 8002
- 客户端发送 RESOLVE 消息的端口为 8008
- 服务器发送 REGISTER 消息的端口为 8008(使用广播)
86、修改用例游戏的客户端和服务器组件,使服务器可以向目录服务注册,并且客户端随后可以使用目录服务获取游戏服务器的 IP 地址和端口详细信息。
修改客户端和服务器组件的步骤
1. 服务器端
在服务器启动时,发送
REGISTER
消息到目录服务。消息编码为包含以下格式的字符串:
REGISTER:server_name:port
其中:
server_name
最长为 30 个字符
port
端口号以文本形式表示
示例:
REGISTER:GameServer:8004
使用端口
To_DIRECTORY_SERVICE_PORT 8008
进行广播。
2. 客户端
客户端有两种方式与目录服务交互:
在客户端用户界面设置“联系目录服务”按钮;
在游戏客户端启动时自动联系目录服务。
客户端发送
RESOLVE
请求消息,编码为包含以下格式的字符串:
RESOLVE:server_name
其中:
server_name
最长为 30 个字符
示例:
RESOLVE:GameServer
使用端口
To_DIRECTORY_SERVICE_PORT 8008
进行广播。
客户端需监听端口
From_DIRECTORY_SERVICE_PORT 8002
,接收目录服务的响应消息。
87、将 NTP 客户端功能集成到一个应用程序中。首先研究两个提供的集成了 NTP 库的 NTP 应用程序客户端程序的代码,然后在你自己的应用程序中模仿这种库集成。
可以按照以下步骤操作:
仔细研究两个已提供的集成了 NTP 库的应用程序客户端代码,了解库的初始化、域名解析、时间戳请求等关键步骤的实现方式。
在自己选择的应用程序中,参考已有的代码,进行 NTP 库的初始化,这包括设置通信套接字并将其设为非阻塞模式。
实现域名解析功能,可调用库中的相关方法,内部使用 DNS 解析器联系外部 DNS 服务。
调用库中的方法向外部 NTP 服务发送时间戳请求,并处理接收到的响应。
对集成后的应用程序进行测试,确保 NTP 功能正常工作。
88、开发一个发布 – 订阅应用程序,使用外部事件通知服务(ENS)来解耦应用程序组件。事件类型和值将取决于你选择的应用程序主题;例如,在分布式游戏应用程序中,可能会有新玩家到来和新游戏开始等事件类型。考虑用一种语言开发发布者,用另一种语言开发消费者,以试验异构性和互操作性方面的问题。
以下是开发该发布 – 订阅应用程序的步骤:
确定应用主题并定义事件类型和值,如分布式游戏应用中的新玩家到来、新游戏开始等。
选择两种不同的语言分别开发发布者和消费者,以实现异构性和互操作性。
利用外部 ENS 实现组件解耦,ENS 具有自动定位和连接、支持发布 – 订阅应用、基于事件类型进行动态逻辑关联、独立于应用且可扩展、低延迟等特性。
确保所有消息按照一定方式进行序列化,以便不同语言编写的组件能正确交互。
89、结果是否符合预期?
部分符合。
在实验中,第二部分进程运行时间比预期稍长,因系统中其他进程和调度活动有开销;
第三部分第一个进程仍占50% CPU资源,另两个共享剩余50%,与预期各占33%不同。
ENS测试中未提及是否符合预期相关内容。