0

複数のスレッドを持つアプレットを作成しています。私はいくつかの奇妙な問題を抱えており、それらを以下のクラスまで追跡しました。これはコード全体であり、切り取りはありません。

public class BoundingBox {
    private volatile int top;
    private volatile int left;
    private volatile int bottom;
    private volatile int right;

    public static final int IGNORE  = 0;
    public static final int TOP     = -2;
    public static final int LEFT    = -1;
    public static final int BOTTOM  = 2;
    public static final int RIGHT   = 1;

    BoundingBox(int left, int top, int width, int height) {
        this.top = top;
        this.left = left;
        this.right = left + width;
        this.bottom = top + height;
    }

    public synchronized int top()       { return top;           }
    public synchronized int left()      { return left;          }
    public synchronized int bottom()    { return bottom;        }
    public synchronized int right()     { return right;         }

    public synchronized int width()     { return right - left;  }
    public synchronized int height()    { return bottom - top;  }

    public synchronized void translate(Vector2D vector) {
        left += vector.getX();
        right += vector.getX();
        top += vector.getY();
        bottom += vector.getY();
    }

    public synchronized void alignTo(Point2D point, int hAlign, int vAlign) {
        if ((hAlign != IGNORE && hAlign != LEFT && hAlign != RIGHT)
            || (vAlign != IGNORE && vAlign != TOP && vAlign != BOTTOM))
            throw new IllegalArgumentException();

        /// START DEBUG CODE ///
        if (right - left != width())
            System.out.println("X");
        if (bottom - top != height())
            System.out.println("Y");
        /// END DEBUG CODE ///

        int width = width();
        int height = height();

        if (hAlign != IGNORE) {
            left = point.getX();
            if (hAlign == RIGHT)
                left -= width;
            right = left + width;
        }

        if (vAlign != IGNORE) {
            top = point.getY();
            if (vAlign == BOTTOM)
                top -= height;
            bottom = top + height;
        }
    }
}

XY時々印刷します。ご覧のとおり、width()は として定義されright - leftていますが、これら 2 つが等しくない場合もあります ( と同じheight())。これらの 4 つのフィールドは非公開で、メソッドは同期されているため、何も中断する必要はありませんalignTo。それでも、何かが私のように見えます。

このコードの何が問題になっていますか?

4

1 に答える 1

1

上、左、下、右を揮発性として宣言するだけでは、必要な方法で同期を維持するには不十分です。問題は、これらの変数が、translate メソッドを使用して別のスレッドで変更されているため、alignTo の実行中に変更されていることです。alignTo の間、これらの変数をロックするか、ローカル変数にキャッシュする必要があります。

于 2013-05-09T23:16:42.337 に答える