操作系统第一次实验报告_操作系统临界区问题

更新时间:2024-05-22 20:49:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

操作系统临界区问题

刘唯墨

一、实验目的

本实验讨论临界区问题及其解决方案。实验首先创建两个共享数据资源的并发线程。在没有同步控制机制的情况下,我们将看到某些异常现象。 针对观察到的现象,本实验采用两套解决方案: ? 利用Windows 的mutex 机制 ? 采用软件方案

然后比较这两种方案的性能优劣。

二、实验步骤 1、制造混乱

Windows 操作系统支持抢先式调度,这意味着一线程运行一段时间后,操作系统会暂停其运行并启动另一线程。也就是说,进程内的所有线程会以不可预知的步调并发执行。

为了制造混乱,我们首先创建两个线程t1 和t2。父线程(主线程)定义两个全局变量,比如accnt1 和accnt2。每个变量表示一个银行账户,其值表示该账户的存款余额,初始值为0。线程模拟在两个账户之间进行转账的交易。也即,每个线程首先读取两个账户的余额,然后产生一个随机数r,在其中一个账户上减去该数,在另一个账户上加上该数。代码如下:

#include #include #include

int accnt1=0; int accnt2=0; double begin=0; double end=0; double time=0; int a=1;

//HANDLE hMutex=CreateMutex(NULL,FALSE,NULL); DWORD WINAPI run(LPVOID p) { int counter=0;

int tmp1,tmp2,r;

//WaitForSingleObject(hMutex,INFINITE); begin=GetTickCount(); do {

tmp1=accnt1; tmp2=accnt2; r=rand();

accnt1=tmp1+r; accnt2=tmp2-r; counter++;

} while (accnt1+accnt2==0&&counter<1000000); end=GetTickCount(); time=end-begin;

printf(\进?程¨?%d所¨′用??时o?à间?为a%lf\\n\,a,time); a++;

//ReleaseMutex(hMutex); counter=0; return 0; }

int main(int argc, char *argv[]) {

CreateThread(NULL,0,run,NULL,0,NULL); CreateThread(NULL,0,run,NULL,0,NULL); system(\); return 0; }

执行结果如下:

从运行结果可以看出,每次进程2都可以全部完成,完成一次计数所需要的时间为62ms,而进城1无法全部完成,所用时间不一定。

混乱制造成功。

2、解决方案 方案一:mutex 方案

Windows 操作系统提供了mutex 对象。mutex 状态可以signaled(unlocked) 或者是nonsignaled (locked)。利用mutex 对象,可以方便地实现临界区保护。进入临界区时(在第一个读操作之前),锁住mutex 对象;离开临界区时(在第二个写操作之后),打开mutex 对象。线程的阻塞与唤醒由系统管理,程序员无需干预。以下给出的是在Windows 操作系统下有关mutex 对象操作的提示。创建一个未上锁mutex 对象的代码如下:

#include #include #include

int accnt1=0; int accnt2=0; double begin=0; double end=0; double time=0; int a=1;

HANDLE hMutex=CreateMutex(NULL,FALSE,NULL); DWORD WINAPI run(LPVOID p) { int counter=0; int tmp1,tmp2,r;

WaitForSingleObject(hMutex,INFINITE); begin=GetTickCount(); do {

tmp1=accnt1; tmp2=accnt2; r=rand();

accnt1=tmp1+r; accnt2=tmp2-r; counter++;

} while (accnt1+accnt2==0&&counter<1000000); end=GetTickCount(); time=end-begin;

printf(\进?程¨?%d所¨′用??时o?à间?为a%lf\\n\,a,time);

a++;

ReleaseMutex(hMutex); counter=0; return 0; }

int main(int argc, char *argv[]) {

CreateThread(NULL,0,run,NULL,0,NULL); CreateThread(NULL,0,run,NULL,0,NULL); system(\); return 0; }

运行结果如下:

从运行结果可以看出,利用mutex 方案并测定进城运行时间可以看出,两个进程运行时间大体相同,进程运行完全,从而可以认为mutex方案有效的防止了两个进程的相互交叉和阻碍。

方案二:软件方案

现在假设操作系统没有提供同步原语。这时,我们只能通过编程语言 对变量的操作实现临界区保护。下面给出的是一个概念性的解决方案框 架:

1 /_ CS Algorithm: Peterson Solution _/ 2 int c1 = 0, c2 = 0, will wait ; 3 cobegin

4 p1: while (1) { 5 c1 = 1;

6 will wait = 1;

7 while( c2 && (will wait==1) ); /_wait loop_/ 8 CS1; 9 c1 = 0; 10 program1; 11 } 12 p2: while (1) { 13 c2 = 1;

14 will wait = 2;

15 while( c1 && (will wait==2) ); /_wait loop_/ 16 CS2; 17 c2 = 0; 18 program2; 19 } 上面的方案使用了三个变量c1; c2 和will wait。线程i 试图进入临界 区时首先把变量ci 置为1,接着把变量will wait 的值设置为i(为什么?) 阻塞通过临界区之前的循环实现。当线程退出临界区时,又把变量ci 的值 设置为0。

代码如下:

#include #include #include

int accnt1=0,accnt2=0;

DWORD WINAPI run1(LPVOID p) {

int counter=0;

int tmp1=0,tmp2=0,r;

double begin=0,end=0,time=0; begin=GetTickCount(); do {

tmp1=accnt1; tmp2=accnt2; r=rand();

accnt1=tmp1+r; accnt2=tmp2-r; counter++;

} while (accnt1+accnt2==0&&counter<1000000); end=GetTickCount(); time=end-begin;

printf(\进?程¨?1所¨′用??时o?à间?为a%lf\,time); counter=0; return 0;

本文来源:https://www.bwwdw.com/article/ijt7.html

微信扫码分享

《操作系统第一次实验报告_操作系统临界区问题.doc》
将本文的Word文档下载到电脑,方便收藏和打印
推荐度:
点击下载文档
下载全文
范文搜索
下载文档
Top