C, PHP, VB, .NET

Дневникът на Филип Петров


* Consumer-Producer – едностранна синхронизация с много консуматори и един производител

Публикувано на 29 ноември 2013 в раздел ПИК3 Java.

В този пример има споделен ресурс – чиния с храна. За нея няма ограничение какво количество храна ще поеме, затова producer (в случая Human) ще я пълни още и още независимо дали е пълна или празна. Кучетата ще се редят едно след друго и ще чакат да се напълни чинията. Използва се централен mutex, с който кучето заявява пред човека, че търси „събуждане“ (notify). Това се прави, за да се предотврати race condition, в който две кучета са събудени последователно и второто изяжда съдържанието на празна чиния (първото е изяло всичко, а човекът все още не е успял да сготви ново ястие). Освен това чинията вече е направена като обект, за да може да се синхронизира по него. По този начин се избягва race condition, при който човекът сготвя ястия в периода между пълненето на стомаха на кучето и нулирането на съдържанието на чинията.

public class CP{
  static Dish dish = new Dish();
  static Dog sharo1 = new Dog("Sharo1");
  static Dog sharo2 = new Dog("Sharo2");
  static Dog sharo3 = new Dog("Sharo3");
  static Human ivan = new Human();
  static volatile boolean mutex = false;
  public static void main(String[] args){
    sharo1.start();
    sharo2.start();
    sharo3.start();
    ivan.start();
  }
}

class Dish{
  int dish;
  public Dish(){
    this.dish = 0;
  }
}

class Dog extends Thread{
  int stomach;
  boolean feeded;
  String name;
  public Dog(String name){
    this.name = name;
    this.stomach = 0;
    this.feeded = false;
  }
  public void run(){
    while(this.stomach <= 100){
      try{
        this.getFood();
      }
      catch(InterruptedException e){
        System.out.println(this.name+" will not feed full");
        break;
      }
    }
    System.out.println(this.name+": Woof, woof!");
    this.feeded = true;
    CP.mutex = true;
  }
  void getFood() throws InterruptedException{
    synchronized(CP.ivan){
      if(CP.dish.dish ==0){
        System.out.println(this.name+" waiting for food");
        CP.mutex = true; // ivan should notify me
        CP.ivan.wait();
      }
      this.sleep((int)(Math.random()*500)); // Dog eats
      synchronized(CP.dish){
        System.out.println(this.name+" eats "+CP.dish.dish);
        this.stomach+=CP.dish.dish;
        CP.dish.dish = 0;
      }
    }
  }
}

class Human extends Thread{
  public void run(){
    do{
      try{
        this.cookFood();     
      }
      catch(InterruptedException e){
        System.out.println("Human stopped cooking");
        break;
      }
    }
    while(  CP.sharo1.feeded == false
         || CP.sharo2.feeded == false
         || CP.sharo3.feeded == false);
  }
  void cookFood() throws InterruptedException{
    synchronized(CP.dish){
      this.sleep((int)(Math.random()*100)); // Human cooks
      CP.dish.dish += 10;
    }
    System.out.println("Human cooked 10. Dish = "+CP.dish.dish);
    if(CP.mutex){
      synchronized(this){
        this.notify();
      }
      CP.mutex = false; // I should not notify more dogs yet
    }
  }
}

 



Добави коментар

Адресът на електронната поща няма да се публикува


*