注: この Java 配備ガイドでは、Java SE 6 update 10 リリースより前にリリースされた機能について説明します。最新情報については、Java Rich Internet Application の開発および配備を参照してください。

アプレットのメソッドが同期化されすぎた場合に AWT でデッドロックする

症状

アプレットを Sun Java™ Runtime Environment (JRE™) を使用したブラウザで実行しているときに、アプレットのメソッド、特に java.awt.Component から継承されたメソッドが同期化されすぎるとデッドロックが発生する場合があります。同じアプレットが Microsoft Virtual Machine (VM) では実行できます。

原因

AWT クラスライブラリは、スレッドに対して安全なクラスライブラリとして使用される場合があります。複数スレッドを使用して AWT を介したアクションを実行するアプレットでは、クラスライブラリで同期化の問題に注意するという前提があります。

しかし、AWT クラスライブラリでスレッドに対して安全であることが保証されるのは、AWT イベントディスパッチスレッドから呼び出しが行われたときのみです。Microsoft VM と Sun とでは実装が異なるため、スレッドに対して安全でないコードが一方の VM で問題なく実行できても、もう一方では失敗する可能性があります。

アプレットで使用される悪い実例としては、Microsoft VM で競合状態やデッドロックが発生しないように、アプレットの各メソッドを同期化することが挙げられます。しかし、この場合でもデッドロックが発生する可能性があります。

この問題を回避するには、本当に必要な箇所でだけアプレットで同期を使用し、不必要な同期は削除します。たとえば、

        public synchronized void paint(Graphics g) {
        ....
    }

    public synchronized void dispose() {       
        super.dispose();
        .....
    }

    public synchronized void stop() {
        ....
    }

    public synchronized void destroy() {
        ....
    }

この場合、paintdisposestop、および destroy メソッドは常に専用のスレッドから、paint および dispose メソッドは AWT イベントディスパッチスレッドから、stop および destroy メソッドはアプレットのスレッドからそれぞれ呼び出されるため、これらのメソッドの synchronized キーワードは削除します。このコードを次のように変更します。

        public void paint(Graphics g) {
        ....
    }

    public void dispose() {       
        super.dispose();
        .....
    }

    public void stop() {
        ....
    }

    public void destroy() {
        ....
    }

詳細情報

        Java チュートリアルの「Concurrency in Swing」では、スレッドの問題、および AWT と Swing プログラムの両方に適用されるテクニックを説明しています。


Copyright © 1993, 2013, Oracle and/or its affiliates. All rights reserved.