Добрый день,впервые работаю с потоками и возникла проблема в синхронизации.Потоков всего два - А генерирует значения а B его забирает и выводит себя столько раз,сколько получило от А,потоки общаются между собой через экземпляр класса Callme. Задача осложняется тем,что **кроме методов wait и notify использовать ничего нельзя**,даже флаги. package 5variant_3_lab; class A implements Runnable{//Поток созданный через реализацию Runnable Thread t; Callme target; int i;//переменная для вывода значения генератора public A(Callme targ){ target = targ; t=new Thread(this,"Поток А"); t.start(); } public void run(){ synchronized(target){ try{ i=target.generator(); System.out.println("Поток A сгенерировал значение ["+i+"]"); target.notify(); //Пробудить другой поток target.wait();//Перейти в спящий режим самому } catch(InterruptedException e){} } } } class Callme{ int count; int i; synchronized int common(){ count=i; return count; } synchronized int generator(){ i = (int)(9 * Math.random() + 1); return i; } } class B extends Thread{//Поток созданный через расширение класса Thread Callme target; int count;// Переменная для хранения значения из метода common() B(Callme targ){ super("Поток B"); target=targ; start(); } public void run(){ synchronized(target){ try{ count=target.common(); System.out.println("Поток B забрал значение ["+count+"]"); for(int j=1;j<=count;j++){ System.out.println("Поток В"); } target.notify();// Пробудить другой поток target.wait();//Перейти в спящий режим самому } catch(InterruptedException e){} } } } public class Beliaev_5variant_3_lab { public static void main(String[] args) { Callme target=new Callme(); for(int i=1;i<=5;i++){ new A(target); new B(target); } } } 

Ps Is it possible that this is due to the fact that target.notify () and target.wait () blocks and awakens itself and things don't go on?

    1 answer 1

    It is dangerous to rely on the notify-wait sequence so easy. You must enter a conditional variable indicating that the producer has put a new package in the transfer object (callme).

     boolean canBeTaken; 

    Then at the consumer:

     while(!canBeTaken) cond.wait(); // Забираем посылку canBeTaken = false; // Продюсер может класть снова cond.notifyAll(); 

    Produced by:

     while(canBeTaken) cond.wait(); // Выдаем посылку в callme canBeTaken = true; cond.notifyAll(); 

    And access to canBeTaken must also be thread-safe, otherwise grandfather =)

    Of course, now the producer is blocked until the consumer takes the value. To avoid this, you can organize a queue. canBeTaken in this case will indicate that the queue is not empty.

    • Thanks a lot, it worked. And I also thought that boolean variables are flags, and it turns out that flags are something else =). - HappyElephant