gpt4 book ai didi

java同步方法中的线程安全错误

转载 作者:行者123 更新时间:2023-12-01 19:00:34 24 4
gpt4 key购买 nike

我有这门课

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() 方法中再次检查了该值。为什么?

我不明白,如果动画是同步的,moveCount怎么会超过11?

如果模拟器滞后,这种情况会更频繁地发生。

最佳答案

您正在 synchronized block 中递增和重置 moveCount,但是当您访问 moveCount 变量时,您并未在同一个锁上同步在 getBitmap() 方法中。

这意味着线程 A 可能位于 animate() 方法的中间,并且已将 moveCount 增加到等于 moveCountMax 。然后线程 B 进入 getBitmap() 并在线程 A 将 moveCount 重置为 0 之前读取 moveCount 的值。

一般来说,您不仅需要在写入变量的值时进行同步,还需要在读取变量的值时进行同步(在同一个锁上),特别是如果对该变量进行其中一项操作(例如您的 animate() 方法)涉及复合操作(递增,然后可能重置为 0)

顺便说一句,如果 moveCountMax 是一个常量值 (= move.length),则将其标记为 final

关于java同步方法中的线程安全错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12413987/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com