0

I'm writing an applet with multiple threads. I've had some strange problems an I've tracked them down to the class below. It's the entire code, no snips.

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;
        }
    }
}

X and Y do print sometimes. As you can see, width() is defined as right - left, but it still happens that these two aren't equal (same with height()). Those four fields are private and methods are synchronized, so nothing should interrupt alignTo, right? Still, something does as it seems to me.

What's wrong with this code?

4

1 回答 1

1

将 top、left、bottom、right 声明为 volatile 不足以使它们以您需要的方式保持同步。问题是,这些变量正在使用 translate 方法在不同的线程上进行修改,因此在执行 alignTo 期间正在更改。您需要在 alignTo 期间锁定这些变量,或将它们缓存到局部变量。

于 2013-05-09T23:16:42.337 回答