2012-01-07 72 views
0

我被要求编写解决“读者和作家”问题的程序,所以我做了。不幸的是,由于Stack.peek()的一些问题,它陷入了困境。正如您在下面看到的,Thread-0是RUNNABLE,但它锁定了Biblioteka对象,因此Thread-2不能继续。它不能解锁它,因为它以某种方式卡在同步块中的if条件中。我的猜测是java.util.Stack类无法正确加载。然而,我不能说真的,我在互联网上找不到满意的答案。所以我的问题是:你以前遇到过这样的事吗?你知道我能读到的任何解决方案或任何来源吗?下面我把jstack扔到我身上,和相关的一段代码。线程被锁定在java.util.Stack

"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(); 
     } 
    } 
} 
+2

不是[SSCCE(http://sscce.org/) – Lion 2012-01-07 17:03:02

回答

1

我没有经历整个代码,但据我看到,有很多关于锁定潜力的地方。对同步语句要非常小心。记住,所有Stack方法都是​​。如果可能,请使用Deque实现(例如,ArrayDeque)。

+0

你能不能再点我的任何潜在地用于锁定,因为我通过我的代码去真的很仔细,我已经分析了它试图模拟所有可能的线程切换。但是我唯一不能完全理解的是这行: java.lang.Thread.State:java.util.Stack.peek上的RUNNABLE(未知源) - 锁定<0x29009448>(java.util.Stack) ' 你能解释一下这是什么意思?它锁定在java.util.Stack – 2012-01-08 14:20:37

3

你正在睡觉,同时拿着锁。一种更好的方式暂停是调用wait()

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