Вызов синхронизированного метода из отражения

Мне нужно вызвать некоторые синхронизированные методы через Java Reflection API. Допустим, у меня есть:

public final synchronized void doSomething() {
    Thread.sleep(1000);
}

Если бы я вызывал этот метод напрямую из двух потоков, один поток вошел бы в метод, а другой поток должен был бы ждать, пока первый поток не покинет блок метода (через одну секунду). Тогда другой поток мог бы ввести метод, и все остальные потоки должны были бы ждать.

Есть ли разница, если я не вызываю метод напрямую, а вызываю его через отражение? Будет ли поведение «блокировки» таким же?


person MinecraftShamrock    schedule 05.04.2014    source источник
comment
Если вы используете отражение, ваш код отражения также будет жить в потоке...   -  person Dirk Lachowski    schedule 06.04.2014


Ответы (1)


Поведение блокировки будет точно таким же, как если бы вы вызывали этот метод без отражения. В основном JVM ниже будет выполнять ту же логику. Вы можете попробовать это сами с помощью приведенного ниже фрагмента кода:

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class SynchronizedReflectionTest {

public static void main(String[] args) {
    SynchronizedReflectionTest test = new SynchronizedReflectionTest();

    for(int i=0; i<5; i++) {
        final int finalI = i;
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Method someThing = SynchronizedReflectionTest.class.getDeclaredMethod("someThing", new Class[]{int.class});
                    someThing.invoke(test, finalI);
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
}

public synchronized void someThing(int nr)
{
    System.out.println("Executing someThing from "+nr);
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    System.out.println("Finished executing from nr "+nr);
}

}

Из результатов печати видно, что вызовы методов синхронизированы. Распечатать результаты:

Executing someThing from 0
Finished executing from nr 0
Executing someThing from 4
Finished executing from nr 4
Executing someThing from 3
Finished executing from nr 3
Executing someThing from 2
Finished executing from nr 2
Executing someThing from 1
Finished executing from nr 1

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

person enterbios    schedule 06.04.2014