java - 线程被锁定在 java.util.Stack

标签 java multithreading deadlock

我被要求编写解决“读者和作者”问题的程序,所以我做到了。不幸的是,由于 Stack.peek() 的一些问题,它被卡住了。正如您在下面看到的,Thread-0 是 RUNNABLE,但它锁定了 Biblioteka 对象,因此 Thread-2 无法继续。它无法解锁它,因为不知何故它卡在同步块(synchronized block)中的 if 条件中。我怀疑 java.util.Stack 类未正确加载。但我真的不能说,我在互联网上找不到任何令人满意的答案。所以我的问题是:您以前遇到过类似的事情吗?您知道任何解决方案或我可以阅读的有关此类事情的任何来源吗?下面我放置了 jstack 向我抛出的内容以及相关代码。

"Thread-2" prio=6 tid=0x03a00400 nid=0x1128 waiting for monitor entry [0x0371f00 0]
java.lang.Thread.State: BLOCKED (on object monitor)
        at Biblioteka.wejdzDoKolejki(Biblioteka.java:120)
        - waiting to lock <0x290093d8> (a Biblioteka)
        at Czytelnik.run(Czytelnik.java:37)

"Thread-0" prio=6 tid=0x0130f000 nid=0x1294 runnable [0x0398f000]
java.lang.Thread.State: RUNNABLE at java.util.Stack.peek(Unknown Source)
        - locked <0x29009448> (a java.util.Stack)
        at Biblioteka.run(Biblioteka.java:62)
        - locked <0x290093d8> (a Biblioteka)
<小时/>
import java.util.Stack;
import java.util.concurrent.PriorityBlockingQueue;

public class Biblioteka extends Thread{
    private Stack<Klient> wBibliotece;
    private PriorityBlockingQueue<Klient> kolejka;
    private int ksiazka;

    public Biblioteka(){
        wBibliotece = new Stack<Klient>();
        kolejka = new PriorityBlockingQueue<Klient>();
        ksiazka = 0;
    }
    public void test(){
        int id_pisarzy = 0;
        int id_czytelnikow = 0;
        Klient k;
        Random rand = new Random();
        Random zlote_mysli = new Random();
        while(true){
        try{
            Thread.sleep((long)(Math.random()*1000));
            if(rand.nextInt(10) > 5){
                id_pisarzy++;
                new Pisarz("Pisarczyk #" + id_pisarzy, this, zlote_mysli.nextInt(1000)).start();
            }
            else{
                id_czytelnikow++;
                new Czytelnik("Czytacz #" + id_czytelnikow, this).start(); 
            }
            if(rand.nextInt(10) > 3){
                synchronized(this){
                    if(!wBibliotece.isEmpty()){
                        try{
                        if(wBibliotece.peek().kto() == "Pisarz")
                                Thread.sleep(1000);
                        }catch(InterruptedException e){
                            e.printStackTrace();
                        }
                        k = wBibliotece.pop();
                        System.out.println("Z biblioteki wychodzi: " + k.kto() + " " + k.naImie());
                        if(k.kto() == "Pisarz")
                            notify();
                        }
                    else
                        notify();
                }
            }
        }
        catch(Throwable e){
            e.printStackTrace();
        }
        }
    }
    public void run(){
        Klient k;
        while(true){
            synchronized(this){
            //Dopóki ktoś jest w bibliotece to pracuje
                while(!wBibliotece.isEmpty()){
                //Jeżeli w bibliotece jest Pisarz to czekam aż wyjdzie
                    while(!wBibliotece.isEmpty() && wBibliotece.peek().kto() == "Pisarz"){
                        try{
                            System.out.println("not Working");
                            wait();
                        }
                        catch (InterruptedException e){
                            e.printStackTrace();
                        }
                    }
                //Sprawdzam czy w kolejce jest pisarz
                    if(!kolejka.isEmpty()){
                        while(!wBibliotece.isEmpty() && wBibliotece.peek().kto() == "Czytelnik" && !kolejka.isEmpty() && kolejka.peek().kto() == "Pisarz"){
                            try{
                                wait();
                            }
                            catch(InterruptedException e){
                                e.printStackTrace();
                            }
                        }
                        k = kolejka.poll();
                        wBibliotece.push(k);
                        System.out.println("Do biblioteki wchodzi: " + k.kto()+ " " + k.naImie());
                        k.dziergaj();
                    }   
                }
                try{
                    while(wBibliotece.isEmpty() && kolejka.isEmpty())
                    {
                        try{
                            wait();
                        }
                        catch(InterruptedException e){
                            e.printStackTrace();
                        }
                    }
                    k = kolejka.poll(); 
                    wBibliotece.push(k);            //i daje ją do biblioteki
                    System.out.println("Do biblioteki wchodzi: " + k.kto() + " " + k.naImie());
                    k.dziergaj();
                }
                catch(Throwable e){
                    e.printStackTrace();
                }
            }
        }
    }

    public int czytaj(){
        return ksiazka;
    }

    public void pisz(int ksiazka){
        this.ksiazka = ksiazka;
    }   

    public void wejdzDoKolejki(Klient k){
        kolejka.add(k);
        System.out.println("Do kolejki wchodzi: " + k.kto() + " " + k.naImie());
        synchronized(this){
            notify();
        }
    }
}

最佳答案

您在按住锁的情况下 sleep 。更好的暂停方法是调用 wait()

synchronized(this){
    if(!wBibliotece.isEmpty()){
        try{
        if("Pisarz".equals(wBibliotece.peek().kto()))
                wait(1000); // releases the lock while waiting.

关于java - 线程被锁定在 java.util.Stack,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8771391/

相关文章:

ios - dispatch_sync里面的dispatch_sync导致死锁

java - 如何使用 Hibernate 和 Spring Data JPA 正确注释两个实体之间的关系?

java - json-simple ,从文件中读取

python - 如何在不使用 communicate() 的情况下避免子进程中的死锁

c++ - 在卸载 DLL 期间删除静态对象时退出线程会导致死锁?

c++ - 多线程导致Qt运行时报错

带延迟的 Java KeyListener

java - DateTimeFormatter 异常

java - 线程和中断

python:如何中断正则表达式匹配