Синхронизация с использованием блокировки объекта в Java - PullRequest
2 голосов
/ 03 января 2011

У меня есть две темы: thread1 (печать номеров) и thread2 (печать алфавитов). Моя цель - получить следующий вывод через синхронизацию:

1 2 б 3 с 4 d 5 е

class thread1 implements Runnable {
    public void run() {

        try {

            for (int i = 1; i <= 5; i++) {
                System.out.println("Is Thread1 holding lock of Testing.class?:"+Thread.holdsLock(Testing.class));
                synchronized (Testing.class) {
                    System.out.println("Is Thread1 holding lock of Testing.class?:"+Thread.holdsLock(Testing.class));

                    try {
                        System.out.println(i);
                        Testing.class.notifyAll();
                        System.out.println("Thread1:Going to wait");
                        Testing.class.wait();
                        System.out.println("Thread1:Resuming from wait");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

            }

            System.out.println("Finsihed thread1");


        } catch (Exception e) {
            System.out.println(e);
        }

    }
}



class thread2 implements Runnable {
    char[] alphabets = { 'a', 'b', 'c', 'd', 'e' };

    public void run() {

        try {

            for (int i = 0; i < 5; i++) {
                System.out.println("Is Thread2 holding lock of Testing.class?:"+Thread.holdsLock(Testing.class));
                synchronized (Testing.class) {
                    try {
                        System.out.println("Is Thread2 holding lock of Testing.class?:"+Thread.holdsLock(Testing.class));
                        System.out.println("Thread2:Going to wait");
                        Testing.class.wait();
                        System.out.println("Thread2:Resuming from wait");
                        System.out.println(alphabets[i]);
                        Testing.class.notifyAll();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }


        } catch (Exception e) {
            System.out.println(e);
        }

    }

}


    public class Testing {

        public static void main(String[] args) {
            Testing w= new Testing();
            thread1 t1 = new thread1();
            thread2 t2 = new thread2();
            Thread th1 = new Thread(t1, "");

            Thread th2 = new Thread(t2, "");
            try {
                th1.start();
                th2.start();
            } catch (Exception e) {
                System.out.println(e);
            }

        }
    }

Я получаю вывод:

Является ли Thread1 удерживающим замком Testing.class: ложь

Thread1 удерживает блокировку Testing.class: правда

1

Тема 1: Будем ждать

Является ли Thread2 удерживающим замком Testing.class: ложь

Является ли Thread2 удерживающим замком Testing.class: правда

Тема 2: Будем ждать

Как thread2 получил блокировку Testing.class, когда он был уже заблокирован thread1 ?. Кроме того, есть ли другой элегантный способ добиться этой синхронизации? Заранее спасибо.

Ответы [ 5 ]

1 голос
/ 03 января 2011

Когда вы вызываете метод wait(), поток, в котором вы его вызываете, временно снимает блокировку.Поэтому, пока thread1 ожидает внутри метода wait(), он не удерживает блокировку, и thread2 может получить блокировку.

Когда метод wait() вернется, поток снова удержит блокировку.

Документация API метода wait() в классе Object объясняет это подробно.

1 голос
/ 03 января 2011

Подробнее о Java Concurrency .

. Вызов wait снимает блокировку.

0 голосов
/ 03 января 2011

публичный класс MyClass { MyClass mClass; логическое isFirstStartedRunning = true; public void doTest () { final int [] a = {1,2,3,4,5,6,7,8,9,10}; final char [] c = {'a', 'b', 'c', 'd', 'e', ​​'f', 'g', 'h', 'i', 'j'}; mClass = это; Поток t1 = новый поток (новый Runnable () {

     public void run()
     {
        isFirstStartedRunning = false;
        for(int i = 0 ; i<a.length ; i++)
        {
         synchronized(mClass)
         {
           System.out.print(a[i]+" "); 
           mClass.notify();
            if(i==a.length-1)return;

             try{mClass.wait();}catch(Exception e){}


         }

        }

     }

   });    
   t1.start();
   Thread t2 = new Thread(new Runnable(){

     public void run()
     {
        if(isFirstStartedRunning){
          try{mClass.wait();}catch(Exception e){}
        }
        for(int i = 0 ; i<c.length ; i++)
        {
         synchronized(mClass)
         {
           System.out.print(c[i]+" "); 
           mClass.notify();
           if(i==a.length-1)return;
           try{mClass.wait();}catch(Exception e){}


         }

       }

     }

   });    
   t2.start();

} public static void main (String [] ar) {

  new MyClass().doTest();

} 

} проверьте ответ сейчас

0 голосов
/ 03 января 2011

Это полный рабочий код

открытый класс MyClass

{

MyClass mClass;

public void doTest ()

{

  final  int [] a = {1,2,3,4,5,6,7,8,9,10};
  final  char [] c = {'a','b','c','d','e','f','g','h','i','j'};
   mClass = this; 
   Thread t1 = new Thread(new Runnable(){

     public void run()
     {
        for(int i = 0 ; i<a.length ; i++)
        {
         synchronized(mClass)
         {
           System.out.print(a[i]+" "); 
           mClass.notify();
           try{mClass.wait();}catch(Exception e){}

         }

        }

     }

   });    
   t1.start();
   Thread t2 = new Thread(new Runnable(){

     public void run()
     {
        for(int i = 0 ; i<c.length ; i++)
        {synchronized(mClass)
         {
           System.out.print(c[i]+" "); 
           mClass.notify();
             try{mClass.wait();}catch(Exception e){}
         }

        }

     }

   });    
   t2.start();

} публичная статическая пустота main (String [] ar) {

  new MyClass().doTest();
} 

}

0 голосов
/ 03 января 2011

Основная проблема, с которой вы столкнулись, состоит в том, что вы освобождаете синхронизированный блок, позволяя обоим потокам проходить цикл одновременно.Это означает, что любой поток может получить блокировку в любом порядке.

AFAIK, самое простое решение - использовать флаг.

final int length = 10;
final AtomicBoolean flag = new AtomicBoolean();
new Thread(new Runnable() {
    public void run() {
        for (int i=1;i<=length;i++) {
            while(flag.get());
            System.out.print(i+" ");
            flag.set(true);
        }
    }
}).start();

new Thread(new Runnable() {
    public void run() {
        for (char c='a';c<'a'+length;c++) {
            while(!flag.get());
            System.out.print(c+" ");
            flag.set(false);
        }
       System.out.println();
    }
}).start();

Самый элегантный способ выполнить эту задачу синхронно:иметь одну нить.Потоки специально предназначены для выполнения двух задач с как можно меньшей зависимостью между ними.

BTW

Если notifyAll () вызывается до вызова wait (), уведомление будет потеряно.wait () будет ждать вечно.

Вы создаете объект Тестирования, который вы отбрасываете (удаляете).

Вы перехватываете InterruptedException, которое вы печатаете, и продолжаете, как будто ничего не произошло (т.е. удаляете вложенный улов)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...