多线程线程在java上被锁定。util。堆栈
我被要求写一个解决“读者和作者”问题的程序,所以我写了。不幸的是,由于堆栈的一些问题,它被卡住了。peek()。正如您在下面看到的,线程-0是可运行的,但它锁定了Biblioteka对象,因此线程-2无法继续。它无法解锁它,因为它在同步块中被卡在if状态。我的怀疑是java。util。堆栈类未正确加载。然而,我真的不能说,我在网上也找不到任何令人满意的答案。所以我的问题是:你以前遇到过类似的事情吗?你知道关于这件事的任何解决方案或任何来源吗?下面我放置了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();
}
}
}
# 1 楼答案
你拿着锁睡觉。暂停的更好方法是调用wait()
# 2 楼答案
我没有通读全部代码,但据我所知,有很多潜在的地方可以锁定。对同步语句要非常小心。记住所有
Stack
方法都是synchronized
。如果可能,使用Deque
实现(例如ArrayDeque
)