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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/vb.net/14.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_Synchronization_Thread Safety_Deadlock - Fatal编程技术网

在多线程Java中检测到不合理的死锁

在多线程Java中检测到不合理的死锁,java,multithreading,synchronization,thread-safety,deadlock,Java,Multithreading,Synchronization,Thread Safety,Deadlock,我有一段代码,其中两个实现Runnable的线程类正在运行并共享一个类Buffer的公共对象 虽然据我所知,我已经正确地使用了同步块和wait()和notify()方法,但是当我在try/catch块中使用thread.sleep(0)睡眠线程时,在一些接受的输出结果之后,它将进入死锁 当我用1000ms(即thread.sleep(1000)睡眠线程烹调,用3000ms(即thread.sleep(3000)睡眠线程Bheem时,未检测到问题 这是线程中常见的生产者-消费者场景,我有意将消费者

我有一段代码,其中两个实现Runnable的线程类正在运行并共享一个类Buffer的公共对象

虽然据我所知,我已经正确地使用了同步块和
wait()
notify()
方法,但是当我在try/catch块中使用
thread.sleep(0)
睡眠线程时,在一些接受的输出结果之后,它将进入死锁

当我用1000ms(即
thread.sleep(1000)
睡眠线程烹调,用3000ms(即
thread.sleep(3000)
睡眠线程Bheem时,未检测到问题

这是线程中常见的生产者-消费者场景,我有意将消费者置于生产者之上

p.S.-我已经给出了上一次调整后的输出。实际产量相当大。

public void consume() {

        while (ob.buffer >= 1) {
            synchronized (ob) {
                System.out.println(Thread.currentThread().getName()
                        + "    started eating Ladoos with currently "
                        + (ob.buffer--) + " ladoos in plate");

                try {
                    Thread.sleep(0); // bheem takes 1.5 sec to eat

                    ob.notify();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

        synchronized (ob) {

            try {
                System.out
                        .println("Plate is empty, bheem will wait for ladoos to serve ");
                ob.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }

    public void run() {

        while (true) {

            consume();
        }
    }
以下代码属于Bheem类别

public void consume() {

        while (ob.buffer >= 1) {
            synchronized (ob) {
                System.out.println(Thread.currentThread().getName()
                        + "    started eating Ladoos with currently "
                        + (ob.buffer--) + " ladoos in plate");

                try {
                    Thread.sleep(0); // bheem takes 1.5 sec to eat

                    ob.notify();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

        synchronized (ob) {

            try {
                System.out
                        .println("Plate is empty, bheem will wait for ladoos to serve ");
                ob.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }

    public void run() {

        while (true) {

            consume();
        }
    }
这个在烹饪课上

public void produce() {

        while (ob.buffer < 5) {
            synchronized (ob) {

                System.out.println(Thread.currentThread().getName()
                        + "  started making Ladoos with currently "
                        + (ob.buffer++) + " ladoos in plate");

                try {
                    Thread.sleep(0); // 1 sec time taken to make a ladoo

                    ob.notify();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        synchronized (ob) {

            try {
                System.out.println("Plate is full, cook will wait ");
                ob.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }

    public void run() {

        while (true) {

            produce();
        }

    }
输出

Plate is empty, bheem will wait for ladoos to serve 
Cook  started making Ladoos with currently 0 ladoos in plate
Bheem    started eating Ladoos with currently 1 ladoos in plate
Plate is empty, bheem will wait for ladoos to serve 
Cook  started making Ladoos with currently 0 ladoos in plate
Bheem    started eating Ladoos with currently 1 ladoos in plate
Plate is empty, bheem will wait for ladoos to serve 
Cook  started making Ladoos with currently 0 ladoos in plate
Bheem    started eating Ladoos with currently 1 ladoos in plate
Plate is empty, bheem will wait for ladoos to serve 
Cook  started making Ladoos with currently 0 ladoos in plate
Bheem    started eating Ladoos with currently 1 ladoos in plate
Cook  started making Ladoos with currently 0 ladoos in plate
Cook  started making Ladoos with currently 1 ladoos in plate
Cook  started making Ladoos with currently 2 ladoos in plate
Cook  started making Ladoos with currently 3 ladoos in plate
Cook  started making Ladoos with currently 4 ladoos in plate
Plate is full, cook will wait 
Plate is empty, bheem will wait for ladoos to serve 

当消费者接受最后一个ladoo时,是什么阻止了你的制作人在消费者设法调用
wait()
之前完全填满盘子并调用最后一个
notify()
?同样,当盘子装满时,是什么阻止消费者在制作人进入
wait()
之前拿走最后一个ladoo并调用最后一个
notify()


如果其他线程没有等待接收通知,则调用
o.notify()
不会执行任何操作。也就是说,对象
o
不记得它收到了通知。

为了简化您的生活,请查看
java.util.concurrent
package@rkosegi是的,但即使是在实验中,这种荒谬的结果也应该有一些原因,至少有一个错误是您正在同步块外读取
ob.buffer
。您不仅会错过更新(除非声明为volatile),而且同步块中的状态也无法保证。此外,您的等待条件没有得到适当的保护。您只需输入等待,而不知道缓冲区的状态。等待应该在条件循环下的同步块内完成(您可能会有虚假的唤醒)。我建议阅读《实践中的并发》一书,因为书中还有很多内容。@MPlatvoet我刚刚将
while(ob.buffer<5){
synchronized(ob)进行了交换{
在Bheem类中也一样。仍然是相同的死锁。您的意思是,当jvm从Cook类中while循环的最后一次迭代转移到Cook类中的下一个同步块时,**在这个转移时间之间**消费者线程从等待状态被Cook线程最后接受的while循环迭代的
ob.notify()唤醒;
并进行5次迭代,然后,当Cook类中的立即下一个同步块运行并调用其wait()方法从而释放锁时,使用者的while条件循环的立即下一个同步块运行并调用wait()也会导致死锁情况,因为双方都在等待对方?这就是你想说的?如果我错了,请纠正我。@angrysumit,是:消费者线程清空盘子,离开同步块,丢失其时间片。生产者线程进入同步块,开始填充盘子,调用notify()在每个ladoo.Consumer线程之后,尝试进入第二个同步块,但无法。生产者线程离开同步块。Consumer线程进入第二个同步块,调用wait(),最终永远等待。Consumer线程进入第二个同步块,调用wait(),永远等待。那么什么样的解决方案可以避免这种情况呢?@angrysumit,请阅读Oracle Java教程中关于保护块的内容。基本上,wait()/notify()的全部目的就是实现所谓的保护块: