2013年10月30日星期三

Blocking problem

 This post last edited by the is_zhoufeng on 2013-10-29 09:42:40
questions:
a pond, there are a lot of birds and a lot of fish , birds produce one offspring every minute , every 30 seconds, the fish produce two offspring. Birds every 10 seconds to eat a fish . Build a pond, initialize some fish and birds, see when birds eat the fish .

Reference http://blog.csdn.net/ldh911/article/details/7346262 write an implementation
But sometimes runs successfully, sometimes it will be blocked in BirdThread run method of world.wait (); Department , seeking explanations



package rabitmq01.test02;

import java.util.concurrent.CountDownLatch;

public class BirdFish {

public static void main(String[] args) throws InterruptedException {

Pond pond = new Pond() ;
pond.birdCount = 5 ;
pond.fishCount = 20 ;

BirdThread bt = new BirdThread(pond) ;
FishThread ft = new FishThread(pond) ;

bt.start();
ft.start();

Thread.sleep(100);  //等上面两个线程先执行

while(pond.fishCount > 0){
synchronized (pond) {
pond.time += 10 ;
pond.countDown = new CountDownLatch(2);
pond.notifyAll();
}
pond.countDown.await();
}

System.exit(-1);  

}

}

class Pond{

int birdCount ;
int fishCount ;
long time ;
CountDownLatch countDown ;

public void printInfo(){
System.out.printf("time[%d]:bird[%d],fish[%d]\n" , time , birdCount , fishCount);
}
}

class BirdThread extends Thread{

Pond  pond ;

public BirdThread(Pond pond){
this.pond = pond ;
}

@Override
public void run() {

while(pond.fishCount > 0){
synchronized (pond) {
try {
pond.wait();
} catch (InterruptedException e) {
e.printStackTrace();

if(pond.time % 10 ==0){
if(pond.fishCount >= pond.birdCount)
pond.fishCount -= pond.birdCount ;
else{
pond.fishCount = 0 ;
}
if(pond.time % 60 == 0){
pond.birdCount += pond.birdCount ;
}
pond.printInfo();
}
}
pond.countDown.countDown();
}
}

}

class FishThread extends Thread{

Pond  pond ;

public FishThread(Pond pond){
this.pond = pond ;
}

@Override
public void run() {
while(pond.fishCount > 0){
synchronized (pond) {
try {
pond.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
if(pond.time % 30 == 0){
pond.fishCount += pond.fishCount * 2 ;
pond.printInfo();
}
}
pond.countDown.countDown();
}
}

}


------ Solution ------------------------------------ --------
sofa first
------ Solution - -------------------------------------------
bench
------ Solution - -------------------------------------------
floor triple
----- - Solution --------------------------------------------
you this may result in a deadlock , the birds blocked waiting thread first wake up the main thread , and then wake up the main thread ; also blocked the main thread waits for a bird or a fish thread wakes up and then wake them , this will cause the conditional synchronization sequence deadlock

advice, you can build a model even more simple, the time control is taken out into the main part of the thread , do not mix producers and consumers in
------ Solution --- -----------------------------------------
countdown after the bird thread and fish thread wait until the main thread to notify too, and you'll deadlock .

multithreaded control itself is too much trouble , you should not put so much into the condition variable synchronization process, it is prone to deadlock , and this time related to the design itself should not be the case, you can try this thing out of time to do an update thread dedicated to control , not in the main thread to do synchronized
------ For reference only ------------ ---------------------------


wake up in the main thread using the notifyAll (), it should wake up ah Bird and Fish two threads
Then Bird and Fish thread to see who grab the lock on the first execution , and so two threads are executed after the main thread pond.await () method will be awakened. into the next round of the cycle.
I feel this logical condition no problem ah ?
You say what is meant by conditional deadlock ? Can you elaborate on what
------ For reference only ------------------------------- --------
I have tried several times and found that it is not blocked in BirdThread every time the wait at the run method .
FishThread may also be blocked in the wait at the run method .

That is the main thread pond.notifyAll (); method can sometimes wake BirdThread with FishThread one .
This is what causes it ?
------ For reference only -------------------------------------- -
problem solved.

cause of the problem :
simulation process deadlock
1, BirdThread into the run method and pond.wait () at blocking
2, FishThread into the run method and pond.wait () at blocking
3, Main method ( main thread ) to modify time after calling pond.notifyAll () to wake up all being pond method on the object wait and call pond.countDown.await (); method to block the main thread waits BirdThread with FishThread have been executed before continuing
4, BirdThread wakes up , after executing business call pond.countDown.countDown ();, and immediately go to the next one cycle continues blocked in pond.wait () at
5, FishThread wakes up , after executing business call pond.countDown.countDown ();, did not immediately enter the next cycle , but by the main thread ran in front of the
6, the main thread pond.countDown.await (); wake up. The main thread into the next round loop operations executed after calling pond.notifyAll () to wake up all wait on the object being pond method ( this time only BirdThread in the wait state , so only BirdThread will wake up ) , and then call pond.countDown.await (); method to block the main thread waits BirdThread with FishThread have been executed before continuing
7, FishThread into the next cycle , blocked in wait at .
8, BirdThread blocking wait method wakes up , after executing business call pond.countDown.countDown (); into the next cycle , continue blocking

9, this time FishThread, BirdThread are blocked in wait at , as only BirdThread called once pond.countDown.countDown (); method so the main thread is also blocked in pond.countDown.await ( ) ; Department . Resulting in a deadlock.



Now there is not a good solution is the main thread Thread.sleep (100); into the first line of the while loop , is the main thread is blocked every one cycle 100ms, ensure that the other two threads have been executed , and enters the wait state
------ For reference only ------------------------ ---------------
in wait in the synchronized lock object , it is easy to deadlock.
conditions are too complicated
personal habits synchronized object alone an instance of Object .
You can wait it out

Also, why not carry on after completing the wait, notify after entering the next cycle
but first wait, and then notify done after operation ?
------ For reference only -------------------------------------- -

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;
    }
}

merry wrote
------ For reference only ------------------------------- --------
final settlement in http://blog.csdn.net/is_zhoufeng/article/details/13622415 at

没有评论:

发表评论