模拟多进程之间的同步与互斥.docx

上传人:b****8 文档编号:9991192 上传时间:2023-02-07 格式:DOCX 页数:23 大小:154.89KB
下载 相关 举报
模拟多进程之间的同步与互斥.docx_第1页
第1页 / 共23页
模拟多进程之间的同步与互斥.docx_第2页
第2页 / 共23页
模拟多进程之间的同步与互斥.docx_第3页
第3页 / 共23页
模拟多进程之间的同步与互斥.docx_第4页
第4页 / 共23页
模拟多进程之间的同步与互斥.docx_第5页
第5页 / 共23页
点击查看更多>>
下载资源
资源描述

模拟多进程之间的同步与互斥.docx

《模拟多进程之间的同步与互斥.docx》由会员分享,可在线阅读,更多相关《模拟多进程之间的同步与互斥.docx(23页珍藏版)》请在冰豆网上搜索。

模拟多进程之间的同步与互斥.docx

模拟多进程之间的同步与互斥

操作系统课程设计

一、题目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;

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 管理学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1