Java 可以再次唤醒上下文切换的等待线程吗
我正在努力让我的制作人/消费者工作,我故意不想使用BlockingQueue来理解这里更详细的信息。我知道当我调用object.wait()时,线程会松开锁并进入等待状态,直到有人通知(notify/notifyAll)哪个线程使它返回到阻塞状态,并且如果它获得锁,该线程将进入可运行状态Java 可以再次唤醒上下文切换的等待线程吗,java,multithreading,wait,producer-consumer,context-switch,Java,Multithreading,Wait,Producer Consumer,Context Switch,我正在努力让我的制作人/消费者工作,我故意不想使用BlockingQueue来理解这里更详细的信息。我知道当我调用object.wait()时,线程会松开锁并进入等待状态,直到有人通知(notify/notifyAll)哪个线程使它返回到阻塞状态,并且如果它获得锁,该线程将进入可运行状态 private class Consumer implements Runnable{ private final MyQueue<Integer> queue;
private class Consumer implements Runnable{
private final MyQueue<Integer> queue;
public Consumer(MyQueue<Integer> queue){
this.queue = queue;
}
@Override
public void run(){
while(true){
synchronized (queue) {
//Block till new available
while(queue.isEmpty()){
try {
queue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//Consume
queue.dequeue();
queue.notifyAll(); //Notify people waiting on queue full condition
}
}
}
}
私有类使用者实现可运行{
私有队列;
公共消费者(MyQueue){
this.queue=队列;
}
@凌驾
公开募捐{
while(true){
已同步(队列){
//封锁直到新的可用
while(queue.isEmpty()){
试一试{
queue.wait();
}捕捉(中断异常e){
e、 printStackTrace();
}
}
//消耗
queue.dequeue();
queue.notifyAll();//通知等待队列已满的人员
}
}
}
}
我的问题是(关于上述代码):
我知道通常的CPU调度程序会给每个线程分配一定的时间,以避免上下文切换成本 这种情况不会发生,因为对队列的任何修改都是(或至少应该)从队列上的同步块完成的。因此,在while循环结束和调用
dequeue()
之间,没有其他线程可以修改队列,因为您的线程是持有锁的线程
当然,如果其他使用者也从队列中删除元素而不在队列上进行同步,则会出现此问题。但这只是代码中的一个bug。使用封装是避免此类错误的最佳方法。如果使用BlockingQueue,BlockingQueue类将封装对共享状态的独占访问,并且您不必确保对队列的每个访问都正确同步,因为BlockingQueue可以为您执行此操作。上下文切换的线程是否持有锁并停止执行?该线程将保持锁,直到它离开同步块。线程当前是否正在执行不会改变任何事情。如果调度程序决定在while循环之后和调用dequeue之前切换到其他线程,那么等待锁的所有其他线程将一直被阻塞,直到持有锁的线程被重新调度,并继续执行,直到它离开同步块。谢谢!这非常清楚地表明“线程将保持锁,直到它离开同步块。线程当前是否正在执行不会改变任何东西”。虽然有趣的是,当操作系统上下文切换时,它可能会减慢等待锁定的线程的速度