【操作系统导论】第28章课后习题解答

前言

内容仅作记录,解答有参考别人的地方,请谨慎参考。关于锁,文中我很随意的说法是“上锁”与“开锁”,文雅一点的说法可以说“获取锁”和“释放锁”。

28.1

题目描述

在这里插入图片描述

分析及解答

首先输入指令:./x86.py -p flag.s运行程序:
在这里插入图片描述
可以看到两个线程在执行,再使用指令:cat flag.s查看汇编代码:
在这里插入图片描述

由此我们可以分析出程序代码的大致含义:实现一个简单的自旋锁
大致的程序代码如下:

void lock(int flag)
{
	while(flag==1);
	flag=1;
}
void unlock(int flag)
{
	flag=0;
}
for(int i=1;i>0;i--)
{
	lock(flag);
	count++;
	unlock(int flag);

}

28.2

题目描述

在这里插入图片描述

分析及解答

使用指令:./x86.py -p flag.s -R ax,bx -M flag,count -c运行程序结果如下:
在这里插入图片描述

可以看到程序产生了正确的结果,之后分析代码标志(flag)的变化:
由第一题分析,得出程序和锁的大致代码

void lock(int flag)//线程T0将要执行,需要上锁
{
	while(flag==1);//flag初始为0,所以成功得到锁,自旋停止
	flag=1;//之后将flag设置为1,在该线程临界区执行完之前,其他线程一直自旋
}
void unlock(int flag)//线程临界区中的内容执行完,开锁
{
	flag=0;//设置flag为0,其他线程可以上锁
}
for(int i=1;i>0;i--)
{
	lock(flag);
	count++;//CS
	unlock(flag);
}

由此可以分析标志flag的值的变化,与模拟结果是一致的

28.3

题目描述

在这里插入图片描述

分析及解答

通过第一题中对汇编代码的分析,我们可以知道,这个程序对count进行循环加1操作,并且锁保护的方案为“细粒度”方案(将锁上在循环内部),将bx修改为2时,相当于增加了循环的次数,所以程序所作的工作如下:

void lock(int flag)
{
	while(flag==1);
	flag=1;
}
void unlock(int flag)
{
	flag=0;
}
for(int i=2;i>0;i--)
{
	lock(flag);
	count++;
	unlock(flag);
}

这个时候,由于中断频率很慢(指中断发生之前,一个线程可以执行完),而且程序做了两次循环,所以我们将会看到一个线程在执行过程中做了两次上锁与开锁。由于循环两次,并且有两个线程,所以count的结果最终为4。

输入指令:./x86.py -p flag.s -R ax,bx -M flag,count -a bx=2,bx=2 -c运行程序查看结果:
在这里插入图片描述

可以看到模拟运行结果与分析是一致的。

28.4

题目描述

在这里插入图片描述

分析及解答

当中断发生在正在执行的线程开锁之前时,将导致不好的结果,这是因为当前线程尚未执行完,标志flag仍为1,即使中断发生,另一个线程也无法获得锁的使用,这段时间里该线程占用了CPU,但并未做任何事,只是在进行自旋等待中断发生。
例如:将中断频率设置为4:

输入指令:./x86.py -p flag.s -R ax,bx -M flag,count -a bx=4,bx=4 -i 4 -c运行程序查看结果:
在这里插入图片描述

以前几个中断周期为例,最开始线程T0得到了锁,并将标志flag设置为了1,这时中断发生,由于中断频率较高,T0并未开锁,flag仍为1,当T1开始执行时将一直执行“while(flag==1)”这条语句,也就是说在这个过程中T1一直占用CPU,但并未执行程序内容,所以当中断频率过快或中断发生在线程开锁之前时,将会导致不好的结果,相对的,中断频率刚好发生在一个线程开锁之后将会使CPU得到充分的利用,可以认为是一个好的结果。

28.5

题目描述

在这里插入图片描述

分析及解答

使用指令:cat test-and-set.s查看程序的汇编代码:
在这里插入图片描述

分析汇编代码,可以大致分析出上锁和开锁的代码:
首先利用一个交换函数,这个函数将会把1赋给mutex,之后返回mutex的旧值

int swap(int new,int mutex)
{
	int old=mutex;
	mutex=new;
	return old;
}
之后程序写法与第一题中分析一致:
void lock(int mutex)//获取锁
{
	while(swap(1,mutex)==1);
}
void unlock(int mutex)//释放锁
{
	mutex=0;
}
for(int i=n;i>0;i--)
{
	lock(mutex);
	count++;
	unlock(mutex);
}

28.6

题目描述

在这里插入图片描述

分析及解答

代码总能够按照预期进行工作,但第四题中的问题依然存在,当中断发生在当前执行的线程开锁之前时,将导致另一个线程即使得到了CPU的使用权,也只是占用CPU做自旋,在这种情况下CPU的使用率是不高的。

输入指令:./x86.py -p test-and-set.s -i 7 -R ax,bx -M mutex,count -a bx=5 -c查看程序运行的情况:
在这里插入图片描述

[这里我故意将中断设置为7条指令进行一次,是为了让问题更明显]
观察图中红色方框框选的部分可以看到,这时线程T1已经获得了CPU的使用权,但是该线程只是在循环执行“while(swap(1,mutex)==1);”并未进入临界区进行操作,这种情况下CPU的使用率是很低的。
当每次中断发生在当前线程开锁之前时,将会导致中断后执行的线程一直进行自旋而无法执行相应的操作,导致CPU利用率低,要使CPU利用率得到提高,需要在当前线程释放锁之后再执行中断。

28.7

题目描述

在这里插入图片描述

分析及解答

输入指令:./x86.py -p test-and-set.s -i 10 -R ax,bx -M mutex,count -a bx=5 -P 000011111111 -c模拟在第一个线程中获取锁之后在尝试第二个线程中获取锁的过程:
在这里插入图片描述

可以看到,当第一个线程获取锁之后,随后在另一个线程中尝试获取锁是无法成功,也无法进入临界区执行代码,只有在当前拥有锁的线程释放锁之后,另一个线程才能成功获取锁,由此说明这个锁具有使未获得锁的线程进入临界区的功能,正确的事情发生了。
还需要测试的是当拥有锁的线程释放锁之后,另一个线程再获取锁是否能够成功
由上面的模拟结果就能看到这个测试结果:
在这里插入图片描述
可以看到,当线程T0释放锁之后,T1再次获取锁成功,随后成功进入临界区执行,这说明这个锁在释放之后,其他线程可以获取锁,锁的功能正常。

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鱼树C

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值