4

我已经看到线程可以通过不同的方式进入阻塞状态。我很想知道线程处于阻塞状态后究竟会发生什么。它如何回到运行状态。如果它被 sleep(time) 阻塞,那么它会在 time 毫秒后移动到可运行队列。如果它在 I/O 操作上被阻塞,一旦完成,它就会进入可运行队列。它在等待对象锁时如何进入可运行队列。它如何知道它等待的对象上的锁现在可用。有人还可以解释 I/O 上的阻塞线程如何工作的内部结构吗?如果我对上述任何主题的理解不正确,请纠正我。

谢谢

4

3 回答 3

3

它在等待对象锁时如何到达可运行队列?

如果线程由于试图进入synchronized块而被阻塞,当另一个线程(持有锁)通过退出synchronized同一对象的块来释放锁时,该线程会自动标记为可运行。

如果当前线程由于调用而被阻塞someObject.wait(),则当另一个线程调用时该线程被“释放” someObject.notify()

在字节码级别,它看起来如下:

[load some object, obj, onto the operand stack]
monitorenter  // grab the lock

// do stuff

[load obj onto the operand stack again] 
monitorexit   // release the lock

如果其他人已经持有的锁obj,该线程将一直挂起,monitorenter直到其他线程调用monitorexit

JLS 没有具体说明如何实施monitorentermonitorexit应该实施的具体细节。也就是说,它依赖于 JVM/OS。

有关更多详细信息,请参阅JLS 等待集和通知

于 2011-01-25T14:21:46.453 回答
0

在接近代码的级别上,它看起来像这样:

线程 1:

Object mutex = new Object();
....
synchronized(mutex) {
    //lock to mutex is acquired.
    mutex.wait(); //lock to mutex is released. Thread is waiting for somebody to call notify().
    doSomething();
}

线程 2:

synchronized(Thread1.mutex) {
    //acquires the lock on mutex. 
    //Can be done only after mutex.wait() is called from Thread1
    // and the lock is released
    Thread1.mutex.notify(); // notifies Thread1 that it can be resumed.
}

一般来说,你应该记住 Thread.sleep() 持有资源的锁,但是 Thread.wait() 释放锁并且可以被其他线程通知。

于 2011-01-25T14:22:46.167 回答
-1

AFAIK JVM 使用本机线程。因此,管理线程调度和上下文切换的是操作系统而不是 JVM。

您可以查看实际的 JVM 源代码。它是开放的。

于 2011-01-25T14:23:18.997 回答