0

我正在尝试在 nachos OS 中实现 KThread.join() 方法。我的示例代码片段如下:

private KThread toJoin = null;
public void join() {
Lib.debug(dbgThread, "Joining to thread: " + toString());

Lib.assertTrue(this != currentThread);


    Lib.assertTrue(toJoin == null);
    boolean intStatus = Machine.interrupt().disable();

   if (status != statusFinished) 
   {
       toJoin = KThread.currentThread();
       KThread.sleep();
   }
   Machine.interrupt().restore(intStatus);
}

public static void finish() {
Lib.debug(dbgThread, "Finishing thread: " + currentThread.toString());

Machine.interrupt().disable();

Machine.autoGrader().finishingCurrentThread();

Lib.assertTrue(toBeDestroyed == null); // what is being done in this line?
toBeDestroyed = currentThread;

     if (currentThread.toJoin != null)   
     {
       currentThread.toJoin.ready(); ////what is being done in this line?
     }
currentThread.status = statusFinished;

sleep();
}

我的问题是如果我创建一个父线程并在其中创建一个子线程并调用 child.join() 方法,那么父线程会发生什么?据我说,它会进入睡眠状态,直到子线程完成它的任务。我对吗?我对此还有一些问题:

  1. 什么时候会调用 finish() 方法?是否同时为父线程和子线程调用?
  2. 在finish() 方法中,我注释掉的行中实际做了什么?
4

1 回答 1

0

会提前,我对这门课不太记得了。我记得它的工作方式是孩子会打电话给加入,然后父母必须在孩子恢复之前完成。

要回答您的问题:

  1. 在分配给该线程的进程完成并且线程将被销毁后,将调用 finish 方法。
  2. 您注释掉的第一行检查以确保没有其他线程等待被销毁。(我假设这样做的原因是我们想在队列中给予等待被销毁的线程优先级,但我不记得 100%)。第二行将尝试等待加入的线程添加回就绪队列,因此它将轮流运行,因为我们在 join() 方法中对其调用了 sleep 方法。

    public void join() {
        Lib.debug(dbgThread, "Joining to thread: " + toString());
    
       Lib.assertTrue(this != currentThread);
        // Entering a critical Section
        Machine.interrupt().disable();
        // Check if the queue has been instantiated
        if(joinerQueue == null){
            // Instantiate it
            joinerQueue = ThreadedKernel.scheduler.newThreadQueue(true);
        }
        // Check if the thread is finished
        if (status == statusFinished) {
            return;
        }
        else {
            // We give joinerQueue the lock of this in order to transfer the priority of this thread
            joinerQueue.acquire(this);
            // we are adding the currentThread to the joinerQueue
            joinerQueue.waitForAccess(currentThread);
            // We sleep the currentThread because we need to wait until this thread finishes
            // When this thread finishes we will wake up in the finish() method
            currentThread.sleep();
        }
        Machine.interrupt().enable();
    }
    
    public static void finish() {
        Lib.debug(dbgThread, "Finishing thread: " + currentThread.toString());
        // Critical Section
        Machine.interrupt().disable();
        // Get the threads which are waiting for the currentThread to finish
        ThreadQueue currentQueue = currentThread.joinerQueue;
        // if currentQueue is not null, means there are threads waiting to join
        if(currentQueue != null) {
            // Get the first thread from the queue
            KThread curThread = currentQueue.nextThread();
            // While there are more threads, ready them up
            while ( curThread != null ) {
                curThread.ready();
                currentThread.joinerQueue.acquire(curThread);
                // Get the next thread to ready up
                curThread = currentQueue.nextThread();
            }
        }
    
        Machine.autoGrader().finishingCurrentThread();
    
        Lib.assertTrue(toBeDestroyed == null);
        toBeDestroyed = currentThread;
    
        currentThread.status = statusFinished;
    
        sleep();
    }
    
于 2015-12-07T20:31:15.090 回答