1、TASK1.1任务实现 KThread.join()当前线程 a 在运行,执行 b.join(),则 a 阻塞,直到线程 b 结束,a 继续执行。几个重要的方法禁止中断机制的实现Interrupt 类有一个 boolean 型变量 enabled,其值 true 时,表示允许中断,false 不允许中断。一般方法不希望执行过程中被中断就在方法开始处添加 boolean intStatus = Machine.interrupt().disable();结束处添加 Machine.interrupt().restore(intStatus);关中断 disable()只有一句 return se
2、tStatus(false)设置 interrupt 状态为 false,并且以前的状态保存在 intstatus,开中断处 restore(intStatus)就是将 enabled 值设为 intStatus;这样就实现了开关中断的过程。setStatus(boolean status)方法还模拟了系统内的时间“前进”,当 interrupt 的状态从不可行变为可行,即关中断到开中断,模仿时间前进:tick(true)。KThread.sleep()当前线程没有结束,就将其状态设为”阻塞”,通过调度器类从就绪队列中选择下一个执行的进程,选择过程又与调度器种类与策略有关。Lib.assert
3、True(s)Lib 里面是一些写好了的函数库,Lib.assertTrue 如果括号内语句为 false,则抛出一个异常.抽象类 threadqueue 有 waitForAccess(KThreadthread)和 acquire(KThreadthread)两个抽象方法,threadqueue 我是这样理解的:一个线程队列等待着某个资源,所以每个临界资源可以用当前等待着的线程队列来指代, waitForAccess(t)说明 t 也加入到该资源的等待队列了,acquire(t)则表示 t 已经得到这个资源了。抽象类 Scheduler 里有个方法 newThreadQueue(boole
4、antransferPriority)该方法构造了一个线程队列,调度器在线程等待队列 选择 下一个可获得资源访问权限时需要使用一个参数,姑且称为“优先级”,优先级高的可得到资源,这会导致饥饿,如 cpu 也是一个资源,就绪队列等待cpu 资源,如果 ABC 三个线程优先级分别是 321,B 等待着 C 所占有的一个资源,C 只有运行结束才释放这个 B 等代着的资源,C 当前拥有 cpu,当根据普通优先级调度方法它无法获得 CPU,进而 B 也无法执行,所以就约定当前获得CPU 线程优先级可以直接设为不小于等待队列中最大的优先级,以便于优先级小的线程快点结束释放其拥有的资源代码在 KThread
5、.java 中:private ThreadQueue joinQueue = null;每个 kthread 对象都有自己的 joinQueue,由由对本线程调用 join 方法的其他线程对象构成,可“捐赠”优先级private boolean Joined = false;布尔形变量 joined,判断本线程是否被其他线程调用过 join 方法,完善 finish()方法时会用到public boolean IsAlive()if(this.status=statusNew|status=statusReady| status=statusRunning|status=statusBloc
6、ked)return true; else return false;一个简单的判断线程是否结束的方法,Kthread 有五种状态,只要状态不为finished,就返回 truepublic void join() Lib.debug(dbgThread, Joining to thread: + toString();Lib.assertTrue(this != currentThread);if (this.status = statusFinished) return;boolean intStatus = Machine.interrupt().disable();/关中断this.h
7、asBeenJoined = true;/设置 join 标志,在 finish 方法中使用if (this.joinQueue = null) this.joinQueue = ThreadedKernel.scheduler.newThreadQueue(true);this.joinQueue.acquire(this);/新建一个可转让优先级的线程队列joinqueue,调用 join 方法的进程直接拥有该队列的最高优先级this.joinQueue.waitForAccess(KThread.currentThread();/currentThread()等待在队列上KThread.
8、sleep(); Machine.interrupt().restore(intStatus);public static void finish() Machine.autoGrader().finishingCurrentThread(); if (currentThread.Joined) currentThread.joinQueue.nextThread().ready();/currentThread 结束前检查 Joined 标志,有等待线程的就选择一个加入就绪队列Lib.assertTrue(toBeDestroyed = null); toBeDestroyed = curr
9、entThread; currentThread.status = statusFinished; sleep();/执行就绪队列下个线程在 join 类测试代码里创建 AThread 和 Bthread 两个线程,AThread 循环打印“AThread 循环第. 次”语句,Bthread 开始打印“B_thread 就绪”语句,中间执行 AThread。Join()方法, 最后打印“B_thread 执行结束”语句。根据结果可以验证基本实现了 join()方法TASK1.2用允许/屏蔽中断的方法实现条件变量Condition 类中已有利用信号量实现的条件变量,我们需要实现不依靠信号变量的实
10、现,Condition 最重要的部分是对 Lock 类的使用,Lock 可被视为线程运行必需的“资源”,拥有 lock 资源的线程才能访问一些临界资源, 即不能被多线程同时访问或修改的资源,lock 对象拥有一个 ThreadQueue waitQueue,且优先级转让标志为 true,这意味着获得 lock 的线程不会因为优先级问题失去该lock。Lock.release()方法让当前拥有锁的线程放弃锁,通过 lockHolder=waitQueue.nextThread()来实现。Lock.acquire()方法要求得到锁,若要求时锁没被其他线程拥有,则调用acquire()方法的线程直接
11、得到锁,否则将调用 acquire()方法的线程加到lock 对象的 waitQueue 中等待。Condition2 类也有一个 waitQueue,用来存放等待在条件变量上的线程,sleep 方法的核心是在 conditionLock.release();KThread.sleep();/conditionLock.acquire();过程中,线程调用Condition2.sleep()方法后,失去锁,阻塞在 conditionlock 这个资源上, 要 acquire()才能结束 sleep()方法。condition.Wake()只能被拥有conditionLock 资源的线程执行,故
12、可实现一个线程等待条件变量的条件成立而挂起;另一个线程使条件成立;互斥锁的使用为了防止竞争,与条件变量结合在一起。public class Condition2 public Condition2(Lock conditionLock) this.conditionLock = conditionLock;waitQueue = new LinkedList();public void sleep() Lib.assertTrue(conditionLock.isHeldByCurrentThread(); boolean intStatus = Machine.interrupt().dis
13、able();/关中断waitQueue.add(KThread.currentThread();/当前线程被添加到条件变量的等待队列上conditionLock.release();/释放锁/线程状态设为阻塞/要求锁,这是线程阻塞的原因Machine.interrupt().restore(intStatus);/开中断public void wake() Lib.assertTrue(conditionLock.isHeldByCurrentThread();/只能被拥有 conditionLock 资源的线程执行/关中断waitQueue.remove().ready();/直接将 wa
14、itQueue 里的线程移出并将其状态设为 readypublic void wakeAll() Lib.assertTrue(conditionLock.isHeldByCurrentThread(); while (!waitQueue.isEmpty()wake();/利用 while 循环将 waitqueue 里所有线程“唤醒”private Lock conditionLock;private LinkedList waitQueue;在 Condition2 测试方法里创 建 共 有 条 件 变 量 c2test, 一 个 临 界 资 源 count 和 三 个 线 程 , thread1,thread2,thread3,初始化三个线程后 thread1,thread2 调用 c2test.sleep() 后开始“睡眠”,thread3 调用 c2test.wakeAll()唤醒所有线程,thread1,thead
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1