模拟多进程之间的同步与互斥.docx
- 文档编号:9991192
- 上传时间:2023-02-07
- 格式:DOCX
- 页数:23
- 大小:154.89KB
模拟多进程之间的同步与互斥.docx
《模拟多进程之间的同步与互斥.docx》由会员分享,可在线阅读,更多相关《模拟多进程之间的同步与互斥.docx(23页珍藏版)》请在冰豆网上搜索。
模拟多进程之间的同步与互斥
操作系统课程设计
一、题目2
二、设计部分2
2.1基本原理2
2.2算法实现2
2.3整体框图3
2.4局部框图4
三、结果:
7
四、遇到的主要问题11
五、代码实现:
12
六、总结21
一、题目
编程模拟多进程之间的同步与互斥。
二、设计部分
2.1基本原理
虽然进程具有异步特性,但系统中的各进程并不是彼此孤立的。
由于种种原因,它们之间常常相互作用并存在某种依赖或相互制约的关系。
为完成同一任务而相互合作的进程称为伙伴进程。
伙伴进程在执行过程中往往需要互通消息或相互等待。
例如,甲进程运行到某点时,要求乙进程为它提供信息,在未得到这一信息时,甲进程阻塞自己直到接受到消息。
进程间的这种协同关系称为进程的同步。
同步多发生在相互有逻辑关系的同组进程之间。
而互斥既可在在同组也可在不同组的进程间存在,因为或许进程间本无关系,只是在竞争资源时由于资源的原因而产生了联系。
所以广义的看,互斥是一种特殊的同步。
2.2算法实现
通过用一个整形变量的数值来模拟存在的资源个数,让进程在访问资源的过程中体现进程间的同步与互斥。
具体思路如下(开发工具:
Delphi7.0):
我们可以通过线程来模拟存在的多个进程。
在delphi7.0中,过程synchronize(procedures)就可以用来管理多个线程之间的同步。
参数s是一个过程名。
执行synchronize的时候,将参数s插入其消息队列中,然后依次调用,从而实现多线程之间的同步。
设计中可以用线程来模拟进程对多个资源的访问。
当某个进程要申请一个资源时,将资源数减1,若其值小于0则表示有进程在等待资源(就体现了进程在使用资源过程中的互斥操作)。
用sleep(times)来模拟进程的使用资源;之后,释放资源,将资源数加1。
若资源数小于0,则唤醒一个等待的进程(体现了进程间的同步操作),分配资源。
通过进程的重复申请资源,来模拟唤醒功能。
用到的主要函数:
1、主进程部分
功能部分:
(1)根据线程的请求分配资源:
将该资源分配给申请线程,同时显示一下分配情况;如果值小于0,则表示等待分配资源状态;调功能(3)显示状态信息;
(2)根据线程的请求释放资源:
如果进程使用资源结束,则将资源数加1,若小于0,则唤醒一个等待的进程,并调功能(3)显示状态信息;
(3)显示状态:
如当前的状态,临界区资源的个数等;
数据部分:
(1)要创建线程的名称列表(线程的名字不能相同);
(2)用一个整形变量来模拟临界区资源的个数;
2、子线程部分
功能部分:
(1)申请资源:
向主线程申请资源,如果成功,进入资源并利用,如果不成功,循环等待并SLEEP,重试n次后仍没有资源可利用,线程终止(以免死锁)并报错误信息
(2)模拟使用:
申请得资源后,随机使用一段时间
(3)申请释放;释放资源要向主进程提供申请,如果成功,那么停止,如果不成功,循环等待并SLEEP,如果重试n次后仍然无法释放资源,则报错误信息并终止;
数据部分:
(1)线程的名称,由线程创建时由主线程指定;
(2)运行时间,等待时间,重试次数,由创建的指定;
(3)休眠时间:
如果申请不到资源或不能申请退出等待的时间
(4)显示的信息列表:
显示的信息有线程名,运行时间,重试次数,现在状态等情况
2.3整体框图
2.4局部框图
调用过程execute(),运行线程
K:
=0
Repeat
Until
K>retrytime
Synchronize(wantsource)
iswantsource
true
False
break
Sleep(waittime)
Inc(k)
k>retrytime
true
False
Synchronize(self.showerror)
Self.terminate;exit
Synchronize(wantsourceok)
Sleep(times)
I:
=0
Repeat
Until
i>retrytime
Synchronize(donwantsource)
isdonwantsource
True
False
Break
sleep(waitTime);
Inc(i);
i>retrytime
True
False
synchronize(self.ShowErrorEx);
self.Terminate;
synchronize(donWantSourceOk);
synchronize(EndThisRun);
过程Wantsource()
//申请资源
strToint(edtuse.text)-1<0
True
False
k=0
k=0
True
False
True
false
edtuse.Text
:
=intTostr
(strToint(edtuse.text)-1);
self.isWantSource:
=false;
edtuse.Tex
t:
=intTostr(strToint(edtuse.text)-1);
self.isWantSource:
=True;
self.isWantSource
True
False
AddinfoTolvinfo(ListIndex,'申请资源成功');
Addinfo(format('进程%s试图申请资源---当前还有可用资源,申请成功',[strname]));
AddinfoTolvinfo(ListIndex,'申请资源失败');
Addinfo(format('进程%s试图申请资源---临界资源没有了,申请失败,等待%d毫秒再试',[strname,waittime]));
过程donwantsource()
//释放资源
isDonotWantSource:
=notCheckBox1.checked;
isDonotWantSource
True
False
edtuse.Text:
=intTostr(strToint(edtuse.text)+1);
AddinfoTolvinfo(ListIndex,'释放资源成功');
Addinfo(format('进程%s试图释放资源---资源尚未锁定,释放成功',[strname]));
AddinfoTolvinfo(ListIndex,'释放资源失败');
Addinfo(format('进程%s试图释放资源---',[strname]));
Addinfo(format('资源被用户锁定,释放失败,等待%d毫秒再试',[waittime]));
ShowError()
//在允许进程释放资源的情况下,重试次数超过预定的
edtuse.text:
=intTostr(strToint(edtuse.text)+1);
addinfoTolvinfo(ListIndex,'超时错误并停止');
addinfo(format('进程%s经过%d次重试,仍然没有成功,超时并终止线程',[strName,RetryTime]));
ShowErrorEx()
//在不允许进程释放资源的情况下,重试次数超出。
强制进程释放资源
addinfoTolvinfo(ListIndex,'超时错误并停止');
addinfo(format('进程%s经过%d次重试,用户仍然锁定不准释放资源---',[strName,RetryTime]));
addinfo('为了防止死锁,强制释放并终止线程');
edtuse.Text:
=intTostr(strToint(edtuse.text)+1);
三、结果:
运行前:
运行中:
当进程被强制不能释放资源时:
当重试次数超过设定的次数时,会终止进程;
四、遇到的主要问题
1、进程申请资源时,先使资源数减1,若小于0,则表示临界资源不够,资源申请失败。
此时,进程会等待一定的时间之后去重试申请资源(模拟唤醒进程操作),在这个时候资源数是不能再减1的。
因为第一次已经表示有分配资源了。
同样,在等待的过程中,若有进程释放了资源,此时申请分配资源,也不能够再减1。
通过定义一个全局变量k,当k=0的时候,表示第一次申请资源;否则,当k>0,则意味着已经该进程在重试申请资源,此时不再执行资源个数减1的操作了。
2、当Tedit控件中的内容为空时,使用函数strtoint(),将Tedit控件中的内容转换为整形则会出错,所以在这个属性中默认一个初值0,这样就可以解决这个问题了。
五、代码实现:
unituMain;
interface
uses
Windows,Messages,SysUtils,Variants,Classes,Graphics,Controls,Forms,
Dialogs,ExtCtrls,StdCtrls,ComCtrls,Buttons,Spin;
type
TMain=class(TForm)
GroupBox1:
TGroupBox;
lbox:
TListBox;
Panel1:
TPanel;
StatusBar1:
TStatusBar;
GroupBox3:
TGroupBox;
GroupBox4:
TGroupBox;
Label3:
TLabel;
Label4:
TLabel;
btnCreate:
TBitBtn;
edtName:
TEdit;
Label5:
TLabel;
Label6:
TLabel;
GroupBox5:
TGroupBox;
Label8:
TLabel;
edtSource:
TEdit;
edtUse:
TEdit;
Label9:
TLabel;
lvInfo:
TListView;
Splitter1:
TSplitter;
Label2:
TLabel;
Label7:
TLabel;
Label10:
TLabel;
CheckBox1:
TCheckBox;
edtWaitTime:
TEdit;
edtTimes:
TEdit;
edtRetry:
TEdit;
procedurebtnCreateClick(Sender:
TObject);
private
{Privatedeclarations}
public
procedureAddInfoTolvinfo(index:
integer;s:
string);
procedureAddInfo(s:
string);
{Publicdeclarations}
end;
TDemoProcedure=class(TThread)
public
ListIndex:
integer;
strName:
string;
WaitTime,RetryTime,Times:
Integer;
isWantSource:
boolean;//申请资源标志
isDonotWantSource:
boolean;//释放资源标志
constructorCreate();
private
{Privatedeclarations}
protected
procedureExecute;override;
procedureWantSource;
procedureWantsourceok;
proceduredonWantSource;
proceduredonWantsourceOK;
procedureEndThisRun;
procedureShowError;
procedureShowErrorEx;//释放资源被锁定,强制释放以防死锁
end;
const
sRun='运行状态';
sWait='申请资源';
sWaitOk='申请资源成功,进行使用期';
sExit='申请释放资源';
sExitOk='释放资源ok';
var
k:
integer;
Main:
TMain;
implementation
{$R*.dfm}
procedureTMain.btnCreateClick(Sender:
TObject);
var
strName:
string;
waitTime,Retry,Times:
integer;
p:
TListitem;
isMore:
boolean;//判断该进程是否已存在
i:
integer;
DemoProcedure:
TDemoProcedure;
begin
strName:
=Trim(edtName.Text);
waitTime:
=strToint(Trim(edtWaitTime.Text));
Retry:
=strToint(Trim(edtRetry.Text));
Times:
=strToint(Trim(edtTimes.Text));
ifTrim(edtName.Text)=''then
beginShowMessage('模拟进程的名称不能为空');edtName.SetFocus;exit;end;
if(WaitTime<=0)then
beginShowMessage('等待时间不能为空,且要大于0');edtWaitTime.SetFocus;exit;end;
if(Times<=0)then
beginshowMessage('运行时间不能为空,且要大于0');edtTimes.SetFocus;exit;end;
if(Retry<=0)then
beginShowMessage('重试次数不能少于0');edtRetry.SetFocus;exit;end;
isMore:
=false;
fori:
=0tolvinfo.Items.Count-1do
begin
iflvinfo.Items[i].Caption=strNamethen
beginisMore:
=true;break;end;
end;
ifisMorethen
beginShowMessage('模拟进程的名称要唯一');edtName.SetFocus;exit;end;
edtName.SetFocus;
withlvinfodo//如果成功,写入进程信息列表中
begin
p:
=Items.Add;
p.Caption:
=strname;
p.SubItems.Add(intTostr(waitTime));
p.SubItems.Add(intTostr(Retry));
p.SubItems.Add(sRun);
end;
i:
=lvInfo.Items.Count-1;
//创建模拟进程
DemoProcedure:
=TDemoProcedure.Create();//创建进程
DemoProcedure.strName:
=strName;
DemoProcedure.Times:
=Times*1000;
DemoProcedure.ListIndex:
=i;
DemoProcedure.WaitTime:
=waitTime*1000;
DemoProcedure.RetryTime:
=Retry;
DemoProcedure.Resume;//runthethread
end;
procedureTMain.AddInfotoLvinfo(index:
integer;s:
string);
begin
iflvinfo.Items.Count-1 ifindex<0thenexit; lvinfo.Items[index].SubItems[2]: =s;; end; procedureTMain.AddInfo(s: string); begin lbox.Items.Add(s); //Application.ProcessMessages; end; {TDemoProcedure} constructorTDemoProcedure.Create; begin FreeOnTerminate: =True; inheritedCreate(True); end; procedureTDemoProcedure.donWantSource;//释放资源 begin withMaindo begin isDonotWantSource: =notCheckBox1.checked; ifisDonotWantSourcethen begin //释放资源 edtuse.Text: =intTostr(strToint(edtuse.text)+1); AddinfoTolvinfo(ListIndex,'释放资源成功'); Addinfo(format('进程%s试图释放资源---资源尚未锁定,释放成功',[strname])); end else begin AddinfoTolvinfo(ListIndex,'释放资源失败'); Addinfo(format('进程%s试图释放资源---',[strname])); Addinfo(format('资源被用户锁定,释放失败,等待%d毫秒再试',[waittime])); end; end; end; procedureTDemoProcedure.donWantsourceOK;//将相关信息写入信息框 begin withMaindo begin AddinfoTolvinfo(ListIndex,'释放资源'); Addinfo(format('进程%s成功释放资源---释放资源后马上会自动终止本进程',[strname])); end; end; procedureTDemoProcedure.ShowError;//在允许进程释放资源的情况下,重试次数超过预定的 begin withMaindo begin edtuse.text: =intTostr(strToint(edtuse.text)+1); addinfoTolvinfo(ListIndex,'超时错误并停止'); addinfo(format('进程%s经过%d次重试,仍然没有成功,超时并终止线程',[strName,RetryTime])); end; end; procedureTDemoProcedure.ShowErrorEx;//在不允许进程释放资源的情况下,重试次数超出。 强制进程释放资源 begin withMaindo begin addinfoTolvinfo(ListIndex,'超时错误并停止'); addinfo(format('进程%s经过%d次重试,用户仍然锁定不准释放资源---',[strName,RetryTime])); addinfo('为了防止死锁,强制释放并终止线程'); edtuse.Text: =intTostr(strToint(edtuse.text)+1); end; end; procedureTDemoProcedure.WantSource; begin withMaindo begin ifstrToint(edtuse.text)-1<0then begin ifk=0then//首次申请资源,同一个进程重复第二次申请时,不应该再减1了 edtuse.Text: =intTostr(strToint(edtuse.text)-1); self.isWantSource: =false; end else begin ifk=0then//首次申请资源。 当k! =0的时候表明是在重复申请资源的过程中 //有了可用资源了,此时不应该再减1! ! ! 所以有控制语句 edtuse.Text: =intTostr(strToint(edtuse.text)-1); self.isWantSource: =True; end; ifself.isWantSourcethen//申请到了资源 begin AddinfoTolvinfo(ListIndex,'申请资源成功'); Addinfo(format('进程%s试图申请资源---当前还有可用资源,申请成功',[strname])); end else//资源正被其他进程在使用 begin AddinfoTolvinfo(ListIndex,'申请资源失败');//添加到进程信息表中 Addinfo(format('进程%s试图申请资源---临界资源没有了,申请失败,等待%d毫秒再试',[strname,waittime])); //添加相关信息到状态显示框中 end; end; end; procedureTDemoProcedure.Wantsourceok; begin withMaindo begin AddinfoTolvinfo(ListIndex,'使用资源状态'); Addinfo(format('进程%s成功申请资源---正在使用过程中,将运行%d毫秒',[strname,times])); end; end; procedureTDemoProcedure.Execute; var i: integer; begin k: =0; repeat synchronize(WantSource); //主线程将synchronize中参数过程放入到消息队列中,然后逐个的响应这些消息 //而实现进程之间的同步 ifisWantSourcethenbreak//申请到了资源 else//资源正在被其他进程使用 sleep(waitTime); Inc(k); until(k>=retrytime); ifk>=retrytimethen begin//未申请到资源退出 synchronize(self.ShowError); self.Terminate; exit;
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 模拟 进程 之间 同步