同步方法似乎中断了

时间:2013-05-09 22:54:31

标签: java synchronization

我正在编写一个包含多个线程的applet。我有一些奇怪的问题,我跟踪他们到下面的课程。这是整个代码,没有剪辑。

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,但仍然会发生这两者不相等(与height()相同)。这四个字段是私有的,方法是同步的,所以不应该中断alignTo,对吧?不过,有些事情在我看来。

这段代码出了什么问题?

1 个答案:

答案 0 :(得分:1)

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