Android Java中双线程修改score变量后值未更新问题求助
线程间变量可见性问题排查与解决
问题场景
定义了int类型变量score,实现两个线程Hilo1和Hilo2:
- Hilo1每30秒执行一次,在UI线程弹出Toast显示当前score值
- 当某次评估结果为真时启动Hilo2,Hilo2延迟
movementTimeThread时长后,在UI线程调用tranquilo()方法,返回true则给score加1
已确认Hilo2正常执行且tranquilo()返回true,但Hilo1下次显示的score仍为0。
相关代码
Hilo1 代码
class Hilo1 extends Thread { @Override public void run() { while (true) { try { Thread.sleep(30000); runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(Course.this, "SCORE="+score, Toast.LENGTH_SHORT).show(); } }); } catch (InterruptedException e) { e.printStackTrace(); } } } }
Hilo2 代码
class Hilo2 extends Thread { @Override public void run() { try { Thread.sleep(movementTimeThread); runOnUiThread(new Runnable() { @Override public void run() { if(tranquilo(currentHeartRate,higherHeartRate,lowerHeartRate,changeInAcceleration)){ score=score+1; /*textViewPuntuacion.setText("Puntuacion= ");*/ }else { vecesNoCalmado = vecesNoCalmado + 1; } } }); } catch (InterruptedException e) { e.printStackTrace(); } } }
问题根源
普通int类型的score没有线程可见性保证:
Java中每个线程都有自己的工作内存,会缓存共享变量的副本。Hilo2在UI线程修改score后,这个修改只会更新UI线程的工作内存,Hilo1的工作内存里的score副本不会自动同步主内存的新值,导致Hilo1读取的始终是初始的0。
解决方案
方案1:给score添加volatile修饰符
修改变量定义,强制所有线程直接读写主内存中的score值,保证修改后其他线程能立即看到:
volatile int score = 0;
方案2:使用原子类AtomicInteger(更推荐多线程并发场景)
如果后续存在多个线程同时修改score的情况,用AtomicInteger可以避免竞态条件,它的原子操作是线程安全的:
// 初始化 AtomicInteger score = new AtomicInteger(0); // Hilo2中修改score score.incrementAndGet(); // Hilo1中读取score Toast.makeText(Course.this, "SCORE="+score.get(), Toast.LENGTH_SHORT).show();
辅助检查
确认每次评估为真时,Hilo2是通过new Hilo2().start();正确启动的,避免出现线程创建但未启动的情况。
内容的提问来源于stack exchange,提问作者louisMay
相关产品推荐
相关产品推荐

