Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 可以再次唤醒上下文切换的等待线程吗_Java_Multithreading_Wait_Producer Consumer_Context Switch - Fatal编程技术网

Java 可以再次唤醒上下文切换的等待线程吗

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;

我正在努力让我的制作人/消费者工作,我故意不想使用BlockingQueue来理解这里更详细的信息。我知道当我调用object.wait()时,线程会松开锁并进入等待状态,直到有人通知(notify/notifyAll)哪个线程使它返回到阻塞状态,并且如果它获得锁,该线程将进入可运行状态

    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();//通知等待队列已满的人员
}
}
}
}
我的问题是(关于上述代码):

  • 我的线程正在等待,等待后醒来(有人通知) 我拿到锁了
  • 我创建了一个检查队列.isEmpty(),它不是空的,执行转到下一行
  • 就在执行下一行queue.dequeue()之前,CPU上下文切换了我的线程
  • 接下来,当我得到cpu片和锁时,我运行queue.dequeue()并说队列为空

  • 我知道通常的CPU调度程序会给每个线程分配一定的时间,以避免上下文切换成本

    这种情况不会发生,因为对队列的任何修改都是(或至少应该)从队列上的同步块完成的。因此,在while循环结束和调用
    dequeue()
    之间,没有其他线程可以修改队列,因为您的线程是持有锁的线程


    当然,如果其他使用者也从队列中删除元素而不在队列上进行同步,则会出现此问题。但这只是代码中的一个bug。使用封装是避免此类错误的最佳方法。如果使用BlockingQueue,BlockingQueue类将封装对共享状态的独占访问,并且您不必确保对队列的每个访问都正确同步,因为BlockingQueue可以为您执行此操作。

    上下文切换的线程是否持有锁并停止执行?该线程将保持锁,直到它离开同步块。线程当前是否正在执行不会改变任何事情。如果调度程序决定在while循环之后和调用dequeue之前切换到其他线程,那么等待锁的所有其他线程将一直被阻塞,直到持有锁的线程被重新调度,并继续执行,直到它离开同步块。谢谢!这非常清楚地表明“线程将保持锁,直到它离开同步块。线程当前是否正在执行不会改变任何东西”。虽然有趣的是,当操作系统上下文切换时,它可能会减慢等待锁定的线程的速度