1

クラス「Foo」と呼ばれる Web アプリにクラスがあるとします。Spring を使用して Bean を作成するときに呼び出される initialise() メソッドがあります。次に、initialise() メソッドは、外部サービスをロードしてフィールドに割り当てようとします。サービスに接続できなかった場合、フィールドは null に設定されます。

private Service service;

public void initialise() {
    // load external service
    // set field to the loaded service if contacted
    // set to field to null if service could not be contacted
}

誰かがクラス「Foo」で get() メソッドを呼び出すと、initialise() メソッドでサービスが開始されていれば、サービスが呼び出されます。サービスのフィールドが null の場合、外部サービスをロードしてみます。

public String get() {
    if (service == null) {
        // try and load the service again
    }
    // perform operation on the service is service is not null
}

このようなことをすると、同期の問題が発生する可能性はありますか?

4

2 に答える 2

1

toolkitの答えは正しいです。この問題を解決するには、Foo の initialise() メソッドを同期するように宣言するだけです。Foo を次のようにリファクタリングできます。

private Service service;

public synchronized void initialise() {
    if (service == null) {
        // load external service
        // set field to the loaded service if contacted
    }
}

public String get() {
    if (service == null) {            
        initialise(); // try and load the service again
    }
    // perform operation on the service is service is not null
}
于 2008-10-22T23:56:08.453 に答える
0

はい、同期の問題が発生します。

単一のサーブレットがあると仮定しましょう:

public class FooServlet extends HttpServlet {

    private MyBean myBean;

    public void init() {
        myBean = (MyBean) WebApplicationContextUtils.
            getRequiredWebApplicationContext(getServletContext()).getBean("myBean");
    }

    public void doGet(HttpRequest request, HttpResponse response) {
        String string = myBean.get();
        ....
    }

}

class MyBean {
    public String get() {
        if (service == null) {
            // try and load the service again
        }
        // perform operation on the service is service is not null
    }
}

Bean の定義は次のようになります。

<bean id="myBean" class="com.foo.MyBean" init-method="initialise" />

問題は、サーブレット インスタンスが複数のリクエスト スレッドで使用されていることです。したがって、service == null によって保護されたコード ブロックは、複数のスレッドによって入力される可能性があります。

最善の修正 (二重チェックのロックなどを回避する) は次のとおりです。

class MyBean {
    public synchronized String get() {
        if (service == null) {
            // try and load the service again
        }
        // perform operation on the service is service is not null
    }
}

これが理にかなっていることを願っています。そうでない場合は、コメントをドロップしてください。

于 2008-10-22T22:45:28.830 に答える