从反射调用同步方法

时间:2014-04-05 22:02:27

标签: java reflection synchronization block synchronized

我需要通过Java的Reflection API调用一些同步方法。 让我们说我有:

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

如果我直接从两个线程调用此方法,则一个线程将进入该方法,另一个线程必须等到第一个线程离开方法块(一秒钟之后)。然后另一个线程可以进入该方法,任何其他线程都需要等待。

如果我不直接调用该方法但通过反射调用它,有什么区别吗? "阻止" -behaviour会不一样?

1 个答案:

答案 0 :(得分:2)

阻止行为与您在没有反射的情况下调用该方法完全相同。基本上下面的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保证锁定的代码将在同步块中执行,如果它依赖于方法类型的调用,反射机制将完全不安全无用。