数据结构课程设计报告.docx
- 文档编号:29435759
- 上传时间:2023-07-23
- 格式:DOCX
- 页数:14
- 大小:54.43KB
数据结构课程设计报告.docx
《数据结构课程设计报告.docx》由会员分享,可在线阅读,更多相关《数据结构课程设计报告.docx(14页珍藏版)》请在冰豆网上搜索。
数据结构课程设计报告
数据结构课程设计报告
姓名:
***学号:
200516104**班级:
05级04班
所选课题:
5、封锁资源管理子系统
目录
需求分析:
1
背景介绍1
功能要求2
概要设计3
详细设计4
调试分析7
1、需求分析:
1.1、背景介绍
在并发操作的系统中,许多用户可能同时对同一数据进行操作。
并发操作带来的问题是数据的不一致性,并发控制的主要技术是封锁。
封锁资源管理子系统就是通过加锁来控制用户对系统资源的并发使用。
基本的封锁类型有S锁(共享锁)和X锁(排他锁)。
共享锁:
用户A对资源R加上S锁,则只允许A读取R,但不能修改R,其它的用户只能再对R加S锁,直到A释放了R上的S锁。
这就保证了其它用户可以读R但在A释放R上的S锁之前不能对R进行修改。
排它锁:
用户A对资源R加上锁,则只允许A读取和修改R其它用户不能再对R加任何锁,直到A释放了R上的锁。
两种封锁方式的相容矩阵如图所示:
S
X
S
OK
NO
X
NO
NO
相容矩阵
用户使用系统资源前必须申请封锁,即给出申请封锁的对象资源号、封锁方式和用户名。
其中资源号是取值为一正整数。
子系统受封锁请求,根据所保存的封锁状态信息决定请求是否能够获得封锁,进行相应处理,并向用户反馈处理结果。
如果获得封锁,则赋给该请求一个批准号,可以使用该资源;否则需要进入等待队列(赋给该请求一个批准号)。
用户结束对某资源的使用后,应释放封锁(给出封锁对象的资源号和封锁批准号)。
系统受理解锁请求时必须能迅速找到有关对象的封锁状况信息,以进行相应处理。
1.2、功能要求
1)、受理用户资源请求,把用户添加进等待队列或活动队列
2)、受理用户释放资源请求
3)、查看资源活动队列
4)、查看资源等待队列
5)、查看系统所有资源
6)、添加资源
7)、用户读取使用资源
8)、用户修改资源
9)、添加用户
用列图如下:
2、概要设计
此部分为整个核心设计的流程,包括资源结构、用户结构、锁结构、等待队列、活动队列、资源高效存储查询的设计,及请求、释放、读、写资源的实现方式设计。
为满足高效存储、查询资源的要求,可采用散列表为资源建索引,并用链表解决冲突,存储的结构如下图所示:
封锁管理子系统示意图
其中散列表的元素对应为封锁对象,以对象的资源号为散列函数的自变量(即关键码值)。
散列表中元素仅为一个指向封锁对象链表的指针。
LO为封锁对象结点,对应于同一散列地址的封锁对象链接到一个链表中。
LR为封锁请求结点。
每个封锁对象结点带两个封锁请求队列:
活动队列中为当前持有对该对象的封锁请求,等待队列中为正在等待对该对象进行封锁的封锁请求。
LO结点和LR结点均向子系统自己管理的可利用空间表申请。
Hash函数采用求余的方法,在这个系统中应为资源的个数是不确定的,因此hash表的大小也可以随着资源数的不同而改变,我的设计是当记录的个数大于资源个数的五倍时hash表大小翻倍。
而S锁和X锁的设计则采用了多态的方法,设计一个公共的抽象基类:
Lock里面定义了三个接口,XLock和SLock类都派生自这个类,这样就可以用一个指针来操作这两个不同的锁了。
而请求的批准号则是系统自动给的,用户可以通过查看资源的请求队列和活动队列获得批准号,等待队列和活动队列都是基于链表的,这样就不会浪费空间。
用户请求资源顺序图如下:
用户释放资源顺序图如下:
3、详细设计
1)、资源结构
classResource
{
private:
boolx_flag;//X锁标记,为真表示已加X锁
bools_flag;//S锁标记,为真表示已加S锁
ActiveQueue*aqueue;//对应资源的活动队列
WaitQueue*wqueue;//对应资源的等待队列vbvcb
stringresource;//资源内容,x_flag、s_flag队它进行读写控制
intresourceNo;//资源编号,唯一标志这个资源
public:
……
};
2)、用户结构
classUser
{
private:
intnice;//定义用户优先级,nice值越大优先级越高
stringuserName;//定义用户名
public:
……
};
3)、锁结构
classLock
{
public:
virtualcharGet_Lock()=0;
virtualboolAddLock(Resource*resource)=0;
virtualboolFreeLock(Resource*resource)=0;
};
classSLock:
publicLock
{
public:
boolAddLock(Resource*r);//对资源r加X锁
boolFreeLock(Resource*r);//释放r的X锁
charGet_Lock(){return'S';}
};
classXLock:
publicLock
{
public:
boolAddLock(Resource*r);//对资源r加X锁
boolFreeLock(Resource*r);//释放r的X锁
charGet_Lock(){return'X';}
};
4)、等待队列、活动队列设计
用基于链表的队列设计等待和活动队列
链表结点LR定义如下:
staticenumLockType{S,X};//定义锁的类型
classLR
{
public:
intrequest_no;
User*user;
LockTypetype;
LR(User*u,LockTypet,intno){user=u;type=t;request_no=no;}
};
等待队列按用户的nice值插入元素,nice值越大优先级越高,用户就插在队头,最先出队。
活动队列则在队尾插入,等用户释放资源后就从队列中删除相应的结点。
5)、资源高效存储查询的设计
用hash表存储资源LO结点如下:
classLO
{
public:
Resource*index;//存储资源地址
intelement;//关键码值
LO*next;//next指针
LO(int&elemVal,Resource*indexVal)
{element=elemVal;index=indexVal;}
LO(int&elemVal,Resource*indexVal,LO*nextVal)
{element=elemVal;index=indexVal;next=nextVal;}
LO(LO*nextVal=NULL){next=nextVal;}
};
6)、请求、释放、读、写资源的实现接口如下:
voidInit();//新建hash表并且定义所有资源
boolRequest(User*,int,Lock*);//用户请求资源
boolFreeResouse(intre_no,intrq_no);//用户释放资源
boolRead(User*,int,string&);
boolWrite(User*,int,string);
voidPrintActor(intre_no);
voidPrintWaiter(intre_no);
voidPrintResource();
boolAddResourse(intre_no,stringre_str);
4、调试分析
1)、测试加锁的相容性,输入数据源代码如下:
if(hash->search(56,r))//找到编号为的资源
{
if(Request(user1,56,x))
cout<<"User1requestresource56byXlocksuccess!
"< else cout<<"User1requestresource56byXlockfailed! "< if(Request(user2,56,s)) cout<<"User2requestresource56bySlocksuccess! "< else cout<<"User2requestresource56bySlockfailed! "< if(Request(user3,56,x)) cout<<"User3requestresource56byXlocksuccess! "< else cout<<"User3requestresource56byXlockfailed! "< } if(hash->search(10,r))//找到编号为的资源 { if(Request(user1,10,s)) cout<<"User1requestresource10bySlocksuccess! "< else cout<<"User1requestresource10bySlockfailed! "< if(Request(user2,10,s)) cout<<"User2requestresource10bySlocksuccess! "< else cout<<"User2requestresource10bySlockfailed! "< if(Request(user3,10,x)) cout<<"User3requestresource10byXlocksuccess! "< else cout<<"User3requestresource10byXlockfailed! "< } 输出如下: 时间复杂度分析: O (1)因为采用hash表所有插入是常数级的 2)、读写操作测试,输入数据源代码如下: if(Read(user1,10,temp)) cout<<"Theuser1readresource10stringis: "< else cerr<<"Theuser1can'treadresource10'sstring! "< if(Write(user1,10,"update_r10")) cout<<"Theuser1changeresource10'sstringto: update_r10"< else cerr<<"Theuser1can'tchangeresource10'sstring! "< if(Read(user1,56,temp)) cout<<"Theuser1readresource56stringis: "< else cerr<<"Theuser1can'treadresource56'sstring! "< if(Write(user1,56,"update_r56")) cout<<"Theuser1changeresource56'sstringto: update_r56"< else cerr<<"Theuser1can'tchangeresource56'sstring! "< 输出如下: 时间复杂度分析: O (1) 3)、测试活动队列,输入数据源代码如下: PrintActor(10); PrintActor(56); 输出如下: 时间复杂度分析: O(n)需要遍历完整个队列,时间复杂度与队列长度成正比 4)、测试等待队列,输入数据源代码如下: PrintWaiter(10); PrintWaiter(56); 输出如下: 时间复杂度分析: O(n)需要遍历完整个队列,时间复杂度与队列长度成正比 5)、请求释放资源测试,输入数据源代码如下: if(FreeResouse(56,0))//批准号为的请求释放资源 { cout<<"Therequest_no: 0unlockresource56success! "< "< PrintActor(56); PrintWaiter(56); } else cout<<"Therequest_no: 0unlockresource56failed! "< if(FreeResouse(10,3))//批准号为的请求释放资源 { cout<<"Therequest_no: 3unlockresource10success! "< "< PrintActor(10); PrintWaiter(10); } else cout<<"Therequest_no: 3unlockresource10failed! "< 输出如下: 时间复杂度分析: O(n)需要遍历完整个等待队列,时间复杂度与等待队列长度成正比 6)、打印资源,输入源代码如下: PrintResource(); 输出如下: 时间复杂度分析: O(n)需要遍历完整个hashlist,时间复杂度与hash表中元素个数成正比 7)、添加资源测试,输入数据如下: cout<<"请输入资源编号和资源字符串\n"; cin>>no_temp>>str_temp; if(AddResourse(no_temp,str_temp)) cout<<"添加成功! \n"; else cerr<<"输入的资源编号重复! \n"; cout<<"添加后的资源hash表为: \n"; PrintResource(); 输出如下: 时间复杂度分析: O (1)因为采用hash表所以在表中添加数据的时间是常数级别的 4.课设总结: (保存在word文档中)总结可以包括: 课程设计过程的收获、遇到问题、遇到问题解决问题过程的思考、程序调试能力的思考、对数据结构这门课程的思考、在课程设计过程中对《数据结构》课程的认识等内容
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数据结构 课程设计 报告