nachos-java Task1.2 Condition Variables

来源:互联网 发布:网络安全法的特征 编辑:程序博客网 时间:2024/06/05 06:07

Task 1.2 Condition Variables

  • 实验要求
  • 实验关键代码
  • 实验测试代码
  • 关键代码分析
  • 测试结果分析

实验要求

◆ Implement condition variables directly, by using interrupt enable and disable to provide atomicity

◆ We have provided a sample implementation that uses semaphores; your job is to provide an equivalent implementation without directly using semaphores (you may of course still use locks, even though they indirectly use semaphores)

◆ Once you are done, you will have two alternative implementations that provide the exact same functionality

◆ Your second implementation of condition variables must reside in class nachos.threads.Condition2

实验关键代码

变量声明

private LinkedList<KThread> waitQueue;private Lock conditionLock;

方法实现

关键代码主要为sleep()方法,wake()方法和wakeAll()方法。

Sleep()方法:

public void sleep() {    Lib.assertTrue(conditionLock.isHeldByCurrentThread());    conditionLock.release();//释放锁    boolean preState = Machine.interrupt().disable();//关中断    waitQueue.add(KThread.currentThread());//将当前线程加入到waitQueue中    KThread.currentThread().sleep();//让当前线程睡眠    Machine.interrupt().restore(preState);//恢复中断    conditionLock.acquire();//申请锁}

Wake()方法:

public void wake() {    Lib.assertTrue(conditionLock.isHeldByCurrentThread());    boolean preState = Machine.interrupt().disable();//关中断    if(!waitQueue.isEmpty()){//唤醒waitQueue中的一个线程        KThread a = waitQueue.removeFirst();//取出waitForQueue中一个线程        a.ready();//将取出的线程启动    }    Machine.interrupt().restore(preState);//恢复中断}

WakeAll()方法:

public void wakeAll() {    Lib.assertTrue(conditionLock.isHeldByCurrentThread());    while(waitQueue!=null)//将waitQueue中的所有线程均唤醒         wake();}

关键代码分析

思路分析

为什么:对于condition,原先的nachos已经给出一种方式实现,看它内部实现会发现它使用信号量实现了条件变量,但通过查看信号量底层代码,发现信号量是靠线程的睡眠和唤醒实现的,故,可以直接使用线程的睡眠和唤醒来实现信号量。

怎么做:用一个数据结构来存放睡眠的线程,在本实验中采用了LinkedList来存放,每次调用sleep()方法,会将当前线程放入LinkedList,然后让其睡眠;每次调用wake()方法会选择LinkedList里的一个线程将其唤醒;调用wakeAll()方法会将LinkedList里所有线程唤醒。

方法解释

  1. void sleep()方法
    睡眠前先释放锁,然后将线程加入到等待队列中,然后睡眠即可,记得在最后申请锁,这是因为当唤醒该线程时,需要重新申请锁。
  2. void wake()方法
    如果等待队列不为空,则取出一个线程将其唤醒。
  3. void wakeAll()方法
    设置循环,只要等待队列不为空,则执行wake()方法。

关键点和难点

关键点:理解条件变量底层实现,可以通过看nachos已经给出的condition类的方法,分析其内部实现。
难点:理解条件变量的作用,锁的使用以及等待队列的用途。

实验测试代码

本实验测试:将用到condition的地方改为condition2,运行正常即可;
注:(由于在之后的实验用到了condition2,也可以与之后的task一起测试)

测试结果分析

将用到condition的地方全部换为condition2,运行正常。

0 0
原创粉丝点击