2013-05-09 75 views
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,但它仍然發生這兩個不相等(與height()相同)。這四個字段是私人的,方法是同步的,所以沒有什麼應該打斷alignTo,對吧?儘管如此,我覺得還是有些事情會發生。

這段代碼有什麼問題?

+0

您是否要求解釋爲什麼X和Y有時會打印? – nakosspy 2013-05-09 23:00:46

+0

我認爲這是我必須解決的一些更深層問題的症狀。 'right - left' *應該*總是等於'width()',對吧? – gronostaj 2013-05-09 23:02:52

+0

這並不能解釋爲什麼'X'和'Y'有時會打印,但是'vector'不可變?如果沒有,最好在'translate'方法中使用'int'作爲參數。 – 2013-05-09 23:14:16

回答

1

聲明頂部,左側,底部,右側,因爲揮發性不足以使它們以您需要的方式保持同步。問題是,這些變量正在使用translate方法在不同線程上進行修改,因此在執行alignTo過程中會發生變化。您需要在alignTo持續時間內鎖定這些變量,或將它們緩存到局部變量。

+0

這是有道理的,但'translate()'和'alignTo()'是同步的,是否有可能在不同的線程中同時運行? – gronostaj 2013-05-09 23:18:32

+0

使一個方法同步只能防止該方法的多個實例或同步的子方法同時在不同的線程上運行。由於translate不是通過alignTo調用的,它們都可以運行。你可以實現你的alignTo方法來使用translate,而不是手動設置屬性,這可以解決問題。 – 2013-05-09 23:26:27

+1

@FriedSock同步方法鎖定擁有對象,因此同一對象的兩個同步方法不能同時輸入。 – 2013-05-09 23:32:09