0

所以我一直在尝试编写一个涉及线程的java程序。这基本上是一个线程向共享内存资源(下面代码中的单元类)请求移动权限的问题。我将向您展示线程中的代码示例。单元类中提到的三个方法是同步方法,但是它们不实现等待或通知。

public void run() {
    try{
        while(true){
            Random r = new Random();
            Thread.sleep(r.nextInt(1000));
            //asks the class cell permission to move if the cell is free.
            if(cell.asksAccess(xi, yi, xf, yf)){
                cell.releaseCell(xi, yi); //release the previous cell
                move(); // move the object
                cell.blockCell(xi, yi); // blocks the cell where the object is now staying.
                setChanged();
                notifyObservers();
            }
        }
    } catch (InterruptedException e) {
    }
}

private void move() {
    int dx = xf - xi;
    int dy = yf - yi;

    xi += (int) Math.signum(dx);
    yi += (int) Math.signum(dy);
}

就像我之前说的,所有调用的单元类方法都是同步的。我的问题是这没有按我的预期工作,当我进行 sysout 调试时,它表明线程并不总是向前移动,有时它们甚至会回到最初的位置,我不明白为什么因为 move 方法总是告诉他们前进,永远不要后退。这是单元类的同步问题吗?或者它是移动方法?任何帮助将不胜感激。

4

2 回答 2

0

首先,让我们考虑move方法。假如说:

  • , ,和变量是xi,和的实例变量xfyiyfRunnable
  • 没有其他(回调)方法可以访问或更新它们,

那么我们可以得出结论,这些变量是“线程受限的”,不需要同步。

那么问题出在哪里?好吧,我认为它在这里:

if (cell.asksAccess(xi, yi, xf, yf)) {
    cell.releaseCell(xi, yi); //release the previous cell
    move(); // move the object
    cell.blockCell(xi, yi); // blocks the cell where the object is now staying.
    setChanged();
    notifyObservers();
}

我可以看到两个问题:

  • 我想你说过askCellblockCell并在对象releaseCell上同步。cell但问题是“询问、阻止、释放”的顺序必须是原子的。
  • 您的代码似乎在xi, yi... 释放一个单元格(?),然后再次阻止它。这些评论似乎暗示您应该打电话cell.blockCell(xf, yf)

...处理该序列同步的最佳方法是什么?

没有看到相关代码,很难说最好的方法是什么。但是一种方法是对cell对象进行一次调用......然后处理moveand 通知;例如这样的:

if (cell.checkAndMove(xi, yi, xf, yf)) {
    move(); // move the object
    setChanged();
    notifyObservers();
}  

其中checkAndMove在类中定义Cell为:

public synchronized boolean checkAndMove(int xi, int yi, int xf, int yf) {
    boolean ok = this.asksAccess(xi, yi, xf, yf);
    if (ok) {
        this.releaseCell(xi, yi);
        this.blockCell(xi, yi);
    }
    return ok;
}
于 2012-11-17T00:38:52.933 回答
0

私有 void move() 方法应该是同步的。

于 2012-11-16T23:31:06.460 回答