我想知道是否有其他人遇到过这个问题。我游戏中的这部分代码依赖于system.out.println语句来工作。没有它,它将无法正常运作
while(isladder){
t = Map.tiles[(int) (Player.x + 15 + ScrollManager.xoffset) / 32][(int) ((Player.y ) + ScrollManager.yoffset) / 32];
if(t.row == 3 && t.col == 5){
ScrollManager.dy = -.5;
System.out.println(t.row);
}else{
ScrollManager.nogravity = false;
}
}
这是在有人点击向上键时启动的线程。这是我正在制作的2d Minecraft游戏的阶梯。如果没有system.out.println代码,播放器将继续悬浮在空中。有了它,玩家将像正常一样停在梯子的顶端
(更新)我通过添加Thread.sleep(1)来修复此问题,使其运行更顺畅
答案 0 :(得分:1)
你受到线程内存缓存的攻击,这是一种优化技术,当JIT确定给定的内存块没有同步问题时,JIT用它来加速你的程序,并且不需要同步主记忆。
相关问题:How to demonstrate java multithreading visibility problems?
实质上是这样的:
1)JIT加载类,并读入while()
循环
2)isladder
变量未声明为volatile
,并且未通过任何synchronized
方式检索,因此JIT认为:
“哦,这个变量基本上是本地的 - 我在本地拥有线程缓存isladder
的值,只是使用它,所以它运行得更快。”
当您在循环中不包含任何倾向于触发上下文切换的操作时,如Thread.sleep(),System.out.println()I / O,isladder
的缓存值永远不会得到刷新。
虽然Thread.sleep()解决了表面问题,但它没有解决代码中的根问题,即缺乏对游戏状态的同步访问。你发布的这个帖子似乎只是修改了滚动窗口,因此是相当无害的,但是当你有线程控制动画对象,敌人等东西时,糟糕的多线程练习会导致自发的,看似随机的,不可预测的结果。