} class BirdEatFish extends Thread{ public void run() { //System.out.println(" birdeat fish start.."); while(pond.fishCount>0){ synchronized(pond){ pond.fishCount -= pond.birdCount; } System.out.println("bird eat fish "+pond); try {Thread.sleep(1000);} catch (InterruptedException e) { e.printStackTrace();} } } }
public void test(){ new BirdGeneration().start(); new FishGeneration().start(); new BirdEatFish().start(); }
public static void main(String[] args) { new Bird().test(); }
} class Pond{ int birdCount ; int fishCount ; long startMillis = System.currentTimeMillis(); Pond(int b, int f){ this.birdCount = b; this.fishCount = f; } public String toString(){ return " At time "+(System.currentTimeMillis()-startMillis)+": bird:"+birdCount+",fish:"+fishCount; } }凑热闹自己写
在主线程中唤醒使用的是notifyAll() ,它应该会唤醒Bird与Fish两个线程呀
然后Bird与Fish线程看谁先抢到锁就先执行,等两个线程都执行完之后,主线程的pond.await()方法就会被唤醒。 进入下一轮的循环。
我感觉这个逻辑 条件没有什么问题啊?
你说的条件性死锁是指什么? 能不能细说一下
也有可能阻塞在FishThread的run方法的wait处。就是说主线程中的 pond.notifyAll();方法有时候只能唤醒BirdThread与FishThread中的一个。
这是什么原因造成的呢?
模拟出现死锁的过程
1、BirdThread进入run方法并在pond.wait()处阻塞
2、FishThread进入run方法并在pond.wait()处阻塞
3、Main方法(主线程)修改time之后调用pond.notifyAll()来唤醒所有正在pond对象上wait的方法,并调用pond.countDown.await(); 方法来阻塞主线程等待BirdThread与FishThread都执行完成之后再继续
4、BirdThread被唤醒,执行完业务之后调用pond.countDown.countDown(); ,并立即进入下一轮循环继续阻塞在pond.wait()处
5、FishThread被唤醒,执行完业务之后调用pond.countDown.countDown();,并没有立即进入下一轮循环,而是被主线程跑到前面了
6、主线程的pond.countDown.await();被唤醒。 主线程进入下一轮循环,执行完业务之后,调用pond.notifyAll()来唤醒所有正在pond对象上wait的方法,(此时只有BirdThread处于wait状态,所以只有BirdThread会被唤醒),然后调用pond.countDown.await(); 方法来阻塞主线程等待BirdThread与FishThread都执行完成之后再继续
7、FishThread进入下一轮循环,阻塞在wait处。
8、BirdThread阻塞的wait方法被唤醒,执行完业务后调用pond.countDown.countDown();进入下一轮循环,继续阻塞9、此时FishThread、BirdThread都阻塞于wait处 ,由于只有BirdThread调用了一次pond.countDown.countDown();方法 所以主线程也阻塞于pond.countDown.await();处 。造成了死锁。现在有个不是很好的解决办法就是将主线程中的Thread.sleep(100); 放到while循环内的第一行,就是主线程的每一轮循环都阻塞100ms,确保另外两个线程都执行完,并进入了wait状态
条件也太复杂了
个人习惯synchronized的对象单独用Object的一个实例。
你可以吧wait拿出来还有,为啥不是进行完之后wait,notify之后进入下次循环
而是先wait,然后notify之后做操作?
import java.util.concurrent.locks.ReentrantLock;public class Bird {
ReentrantLock lock = new ReentrantLock();
public Pond pond = new Pond(8,20);
class BirdGeneration extends Thread{
public void run() {
while(pond.fishCount>0){
synchronized(pond){
pond.birdCount = pond.birdCount*2;
}
System.out.println("bird gene "+pond);
try {Thread.sleep(6000);} catch (InterruptedException e) { e.printStackTrace();}
}
}
}
class FishGeneration extends Thread{
public void run() {
//System.out.println(" fish gene start..");
while(pond.fishCount>0){
synchronized(pond){
pond.fishCount = pond.fishCount*3;
}
System.out.println("fish gene "+pond);
try {Thread.sleep(3000);} catch (InterruptedException e) { e.printStackTrace();}
}
}
}
class BirdEatFish extends Thread{
public void run() {
//System.out.println(" birdeat fish start..");
while(pond.fishCount>0){
synchronized(pond){
pond.fishCount -= pond.birdCount;
}
System.out.println("bird eat fish "+pond);
try {Thread.sleep(1000);} catch (InterruptedException e) { e.printStackTrace();}
}
}
}
public void test(){
new BirdGeneration().start();
new FishGeneration().start();
new BirdEatFish().start();
}
public static void main(String[] args) {
new Bird().test();
}
}
class Pond{
int birdCount ;
int fishCount ;
long startMillis = System.currentTimeMillis();
Pond(int b, int f){
this.birdCount = b;
this.fishCount = f;
}
public String toString(){
return " At time "+(System.currentTimeMillis()-startMillis)+": bird:"+birdCount+",fish:"+fishCount;
}
}凑热闹自己写