我有这个班级
package net.omnosis.mazegame.components;
import net.omnosis.mazegame.SlicedBitmap;
import android.graphics.Bitmap;
public class PlayerLayer extends DrawableLayer {
private Player player;
private XY tileImageSize;
private int[] move = new int[] { 1, 2, 3, 4, 3, 2, 1, 6, 7, 8, 7, 6 };
//private int[] move = new int[] { 8 };
private int moveCount;
private int moveCountMax = move.length;
private Bitmap playerBitmap;
public SlicedBitmap playerTiles;
private int line;
private static final int VERTICAL = 0;
private static final int HORIZONTAL = 8;
public PlayerLayer(Player player, Bitmap playerBitmap, XY tileImageSize) {
this.playerBitmap = playerBitmap;
this.tileImageSize = tileImageSize;
playerTiles = new SlicedBitmap(playerBitmap, tileImageSize.x(), tileImageSize.y());
setPlayer(player);
update();
}
public final void setPlayer(Player player) {
if (this.player != null) {
this.player.removeListener(this);
}
this.player = player;
player.addListener(this);
update();
}
public void updateDirection() {
Direction dir = player.getHeading();
if (dir == Direction.LEFT || dir == Direction.RIGHT) {
line = HORIZONTAL;
} else if (dir == Direction.TOP || dir == Direction.BOTTOM) {
line = VERTICAL;
}
}
public synchronized void animate() {
if (player.isMoving()) {
moveCount++;
if (moveCount >= moveCountMax) {
player.finishMove();
moveCount = 0;
}
} else {
}
updateDirection();
super.update();
}
public void update() {
updateDirection();
super.update();
}
public XY getSpritePos() {
XY playerPos = new XY(player.getCurrentPosition().x() * tileImageSize.x() + (tileImageSize.x() / 2), player.getCurrentPosition().y() * tileImageSize.y() + (tileImageSize.y() / 2));
XY animationPos = getAnimationPos();
return playerPos.add(animationPos);
}
public XY getAnimationPos() {
double step = (double) tileImageSize.x() / moveCountMax * moveCount;
return player.getHeading().multiply((int) step);
}
public Bitmap getBitmap() {
if (moveCount >= moveCountMax) {
System.out.println("BUG! MORE: " + moveCount + " max: " + moveCountMax);
moveCount = 0;
}
return playerTiles.getTile(move[moveCount] + line);
}
}
一个线程每10毫秒调用animate
方法。有时我得到这个输出:BUG! MORE: 12 max: 12
这是因为我在getBitmap()
方法中检查了值AGAIN。为什么呢?
我不明白,如果动画是synchronized
,那么moveCount如何超过11?
如果模拟器滞后,则会更频繁地发生这种情况。
答案 0 :(得分:3)
您正在moveCount
块中递增并重置synchronized
,但在moveCount
方法中访问getBitmap()
变量时,您没有在同一个锁上进行同步。
这意味着线程A可以位于animate()
方法的中间位置,并且已增加moveCount
以等于moveCountMax
。线程B然后输入getBitmap()
并在线程A将moveCount
重置为0之前读取moveCount
的值。
通常,您不仅需要在写入变量值时进行同步,还需要在从中读取变量时(在同一个锁上)进行同步,尤其是对于该变量的某个操作(例如{{ 1}}方法)涉及复合操作(增量,然后可能重置为0)
顺便说一句,如果animate()
是一个常数值(moveCountMax
),请将其标记为= moves.length
。
答案 1 :(得分:1)
您需要同步对共享可变数据的所有访问权限。您可以对增量进行同步,这很好,但是您不会在getBitmap
中进行同步。这意味着线程可以在moveCount
中读取getBitmap
,同时增加或紧接在后。
想象一下你增加moveCount
的情况,在增量线程将其设置为0之前,另一个线程调用getBitmap,其中if (moveCount >= moveCountMax) {
在那一刻可以为真。