анонимные классы java и синхронизация, и это

Я имею дело с состоянием гонки, я полагаю, в моем графическом интерфейсе JAVA.

У меня есть несколько методов, которые создают "анонимный метод" внутри анонимного класса, например:

synchronized foo()
{
     someMethod(new TimerTask()
     {
          public synchronized run()
          {

               //stuff

          }
     };
}

ВОПРОС: этот метод запуска синхронизирован с объектом TimerTask или классом, в котором находится foo?

ВОПРОС 2: если бы я избавился от «синхронизированного» в объявлении run() и вместо этого получил блок synchronized(this) {} внутри тела run(), будет ли «это» относиться к объекту TimerTask или к объекту, который является экземпляром метода, содержащего foo()?

Пожалуйста, помогите мне здесь.

Спасибо, джбу


person jbu    schedule 30.04.2009    source источник
comment
Это ошибка, которая упоминается даже в книге Java Concurrency In Practice (JCiP). Жаль, что Java так слабо типизирована по отношению к synchronized.   -  person Tom Hawtin - tackline    schedule 01.05.2009


Ответы (4)


Метод run синхронизируется с самим TimerTask. Синхронизированные методы экземпляра всегда синхронизировано на объекте this. (Методы класса синхронизируются с объектом Class.)

Если вы хотите синхронизировать объект, членом которого является foo, вам необходимо определить ключевое слово this. Предположим, что foo() является членом класса Bar, внутри метода run() класса TimerTask вы можете использовать

public void run() {
  synchronized(Bar.this) {
    ...
  }
}
person erickson    schedule 30.04.2009
comment
Синхронизированные методы всегда синхронизируются с этим объектом. -В данном случае трудно различить, ЧТО ЭТО за предмет. Всегда ли это самый внутренний/ближайший класс? - person jbu; 01.05.2009
comment
Да, я думаю, вы могли бы выразить это так. Это экземпляр, членом которого является метод. run() является членом анонимной задачи TimerTask; foo() является членом окружающего экземпляра. - person erickson; 01.05.2009
comment
Было бы веселее, если бы у нас были затворы BGGA. это будет относиться к внутреннему классу в традиционных (ограниченных) затворах, но к внешнему классу в затворах BGGA (более полных). - person Tom Hawtin - tackline; 01.05.2009
comment
Если вы перед этим укажете имя класса, любая предполагаемая двусмысленность будет разрешена. - person George Armhold; 01.05.2009
comment
Обратите внимание, что это означает, что критический блок входит и выходит, а затем другой критический блок (метод run()) входит и выходит. Между этими критическими блоками проходит некоторое время. - person Vikram Bodicherla; 16.07.2014

Я почти уверен в этих ответах, но я не могу найти хороший банкомат с источником.

Первый вопрос:
синхронизированный заблокирует TimerTask.

Второй вопрос:
это относится к TimerTask; если вы хотите заблокировать содержащий объект, вы должны использовать MyContainingObject.this

person Kevin Montrose    schedule 30.04.2009

Существует только один поток, который может иметь доступ к элементам качания. Это AWT-EventQueue-0. Вы должны знать об этом. Если другие ваши потоки прорисовываются или изменяют элементы, существует очень большая вероятность того, что графический интерфейс выйдет из строя. Чтобы запустить графический интерфейс с этим потоком:

  try {
            SwingUtilities.invokeAndWait(new Runnable(){
                public void run(){
                    Swing_Prozor1 prozor = new Swing_Prozor1();
                }
            });
        } catch (InterruptedException e) {
            //namjerno zanemareno
        } catch (InvocationTargetException e) {
            //namjerno zanemareno
        }

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

ClassName.this

хм, этот приведенный выше код говорит мне об этом. Вы дважды защитили часть кода. Когда вы пишете синхронизированный метод, это означает, что только один поток может получить доступ к этому методу одновременно. Другие потоки ожидают разблокировки синхронизированного метода.

person shake    schedule 30.04.2009

Если вы ищете синхронизацию foo() и run(), вы можете создать явный объект блокировки, например

окончательная блокировка объекта = новый объект();

а потом синхронизироваться на нем.

foo() {
    synchronized(lock) {
       someMethod(new TimerTask() {
          public void run() {
              synchronized(lock)  {
                     //stuff
              }
          }
      }
person Manoj    schedule 01.05.2009