nachos课程设计 task1.2

nachos task1.2
要求:
实现条件变量 , 通过中断使能和不使能两种操作提供条件变量上的原子操作。按照  nachos.threads.Condition, 其中已经实现了一个使用信
号量机制的例子。 在不使用信号量的情况下提供一种等同的实现方法 ( 使用锁 ) 。 实现放在  nachos.threads.Condition2  类中 .
思路: threads.Lock  类 提 供 了 锁 以 保 证 互 斥  .  在 临 界 代 码 区 的 两 端 执 行  Lock.acquire()  Lock.release()  即可保证同时只有一个线程访问临界代码区 条件变量建立在锁之上 threads.Condition  实现 它是用来保证同步的工具 每一个条件变量拥有一个锁变量  ( 该锁变量亦可被执行  acquire   release  操作 多个条件变量可共享同一个锁变量 ).  当处于临界区内的拥有某锁  L  的当前线程对与锁  L  联系的条件变量执行  sleep  操作时 该线程失去锁  L  并被挂起 下一个等待锁  L  的线程获得锁  L ( 这个过程由调度程序完成 并进入临界区 当拥有
 L  的临界区内的当前线程对与锁  L  联系的条件变量执行  wake  操作时  ( 通常调用  wake  之后紧接着就是  Lock.release),  等待在该条件变量上的之多一个被挂起的线程  ( 由调用  sleep  引起 被重新唤醒并设置为就绪状态 若执行  wakeall  操作 则等待在该条件变量上的所有被
挂起的线程都被唤醒 . threads.condition  已经实现了一个条件变量  ( 采用信号量实现 ),  题目要求用屏蔽 / 禁止中断的方法再实现一下条件变量  ( 写在  threads.condition2  )
方案:
只需简单修改  threads.condition  的代码即可 . condition.sleep  采用  waiter.P()  实现休眠  (waitor 是一个信号量 并将  waitor  放入信号量队列 在我们的实现中改成用  KThread.sleep() 实现休眠并将当前线程放入线程队列 并在  sleep  函数开始 / 结尾处屏蔽 / 允许中断以保证原子性 ;
condition.wake 
中从等待信号量队列中取出信号量并对其进行  V  操作实现唤醒 在我们的实现中改成从线程队列中取出线程用  KThread.ready()  实现唤醒  ( 同样要在  wake  函数开始 / 结尾处屏蔽 / 允许中断 ), wakeall  函数的实现依赖于  wake.  只需不断地  wake  直到队列为空为止 .

用开关中断的方式来将一个等待该条件变量的线程加入到等待队列中,保证院子操作,临界区用加锁和释放锁的方式来实现院子操作。
首先,需要先定义一个锁变量,一个线程等待队列,一个不需要等待的线程个数。
 private Lock conditionLock;
    private ThreadQueue waitQueue;
    private int value;
然后写  Condition2 的构造方法

public Condition2(Lock conditionLock) {
    this.conditionLock = conditionLock;
    this.waitQueue=ThreadedKernel.scheduler.newThreadQueue(true);;
    this.value=0;
    
    }
当一个线程调用 sleep 方法时,他首先释放拥有的某一个条件变量的锁(这个时候其他的线程可以获得这个锁),然后加入到等待队列里,将自己挂起,直到有人来将他唤醒,他再得到这个锁,进入临界区执行。为保证拜操作的原子性,使用开关中断的方法。
 public void sleep() {
    Lib.assertTrue(conditionLock.isHeldByCurrentThread());

    conditionLock.release();
    
    boolean intStatus = Machine.interrupt().disable();
    value ++;
    waitQueue.waitForAccess(KThread.currentThread());
    KThread.sleep();
    Machine.interrupt().restore(intStatus);
    

    conditionLock.acquire();
    }

    wake
操作是当一个线程使用完临界区时,便唤醒等待在队列中的下一个线程,这也是一个原子操作,需要用到开关中断。
    public void wake() {
    Lib.assertTrue(conditionLock.isHeldByCurrentThread());
    
    if (value > 0) {
        boolean intStatus = Machine.interrupt().disable();
        KThread thread = waitQueue.nextThread();
        if (thread != null) {
            thread.ready();
            value --;
        }
        Machine.interrupt().restore(intStatus);
    }
    }

   wakeall
的思想采用了 condition 的实现方法
    public void wakeAll() {
    Lib.assertTrue(conditionLock.isHeldByCurrentThread());
    KThread thread=waitQueue.nextThread();
    while (thread!=null)
        wake();
        thread=waitQueue.nextThread();
    
    }

   
最后是测试,测试的话可以将用condition的地方换成condition2.然后和之前是一样的效果就成功了。当然后面的几个任务里也会用到条件变量,也可以在那个时候测试,比如在task1.6里就可以测试。详见后面的博客。
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值