2012-01-07 70 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.