0

Proxy オブジェクト ( を実装するオブジェクトjava.lang.reflect.InvocationHandler) で、プロキシされたオブジェクトにインスタンス変数を設定しようとしています。

次のように:

public class ServiceProxy implements InvocationHandler {

    private final Object proxiedObject;

    private ServiceProxy(final Object object) {
        this.proxiedObject = object;
    }

    public static Object newInstance(final Object object) {
        return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), new ServiceProxy(object));
    }


    public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {

        Object result = null;
        MyObject mo = new MyObject();

        // Is the following safe when the proxiedObject is being acceessed by multiple threads?
        final Field sessionField = this.proxiedObject.getClass().getSuperclass().getDeclaredField("mo");
        sessionField.setAccessible(true);
        sessionField.set(this.object, mo);


        result = method.invoke(this.proxiedObject, args);


        return result;
    }
}

これは安全ですか?

編集

実際のコード:

Object result = null;
Session session = HibernateUtil.getSessionFactory().getCurrentSession()

// Is the following save when the proxiedObject is being acceessed by multiple threads?
final Field sessionField = this.proxiedObject.getClass().getSuperclass().getDeclaredField("session");
sessionField.setAccessible(true);
sessionField.set(this.object, session);

result = method.invoke(this.proxiedObject, args);
return result;

Edit2 : プロキシされたオブジェクトは、同じプロキシされたオブジェクトの複数のメソッドを同時に呼び出す GWT クライアントから呼び出されています。これが発生すると、(プロキシされたクラスの) セッション インスタンス フィールドが閉じられ、予期しない方法で開かれます。

4

1 に答える 1

2

proxiedObject が複数のスレッドによってアクセスされている場合、次は安全ですか?

いいえ、そうでないmo限りvolatilemoフィールドが である場合、volatileこれはメモリ バリアを適切に通過し、moフィールドへの更新はすべてのスレッドに表示されます。

MyObjectが不変でない場合、 が であっても同時実行性の問題が発生することを認識することが重要moですvolatile


編集:

これに関する@jtahlbornのコメントに感謝します。私はいくつかの読書をしてきましたが、部分的に初期化されるのを防ぐことvolatileできると確信しています。MyObject

コンストラクター命令の並べ替えの可能性によりMyObject、参照先がスレッド間で共有されている場合、完全に構築されているという保証はありません。finalコンストラクターの終了時に正しく初期化されることが保証されるのは、コンストラクター内のフィールドだけです。他のフィールドは初期化されている場合とされていない場合があるため、複数のスレッドがオブジェクトへのアクセスを開始する前に、オブジェクトを同期する必要があります。

ただし、フィールドが揮発性である場合、「発生前」の保証により、が完全に初期化されているmoことも保証されます。MyObjectコンパイラーは、volatile変数の公開を過ぎてこれらの命令を並べ替えることはできません。見る:

于 2012-07-19T16:23:12.400 に答える