Java并发问题:使用synchronized关键字仍得到错误结果
问题原因与修复方案
核心问题1:主线程未等待子线程执行完毕
你在主线程中启动tA和tB两个线程后,立刻调用getRawBalance()打印余额,但此时这两个子线程可能还没开始执行、只完成了一个,或者刚好都执行完。主线程和子线程的执行顺序由操作系统调度决定,所以每次运行的结果都不确定。
核心问题2:getRawBalance()存在可见性问题
balance是非volatile变量,且getRawBalance()没有同步机制。即使子线程已经完成存款操作,主线程也可能无法读取到balance的最新值,因为线程的工作内存和主内存之间的更新没有同步保证。
额外bug:rawWithDraw()的判断逻辑错误
rawWithDraw()里的判断条件写的是if (balance >= balance),这永远为true,不管余额是否足够,都会执行扣款,这是明显的逻辑错误,应该改成if (balance >= amount)。
修复后的代码示例
修改后的Main类(等待子线程执行+用同步方法获取余额)
public class Main { public static void main(String[] args) throws InterruptedException { Account account1 = new Account(0); Thread tA = new Thread(() -> account1.safeDeposit(70)); Thread tB = new Thread(() -> account1.safeDeposit(50)); tA.setName("thread-A"); tB.setName("thread-B"); tA.start(); tB.start(); // 等待两个子线程执行完成 tA.join(); tB.join(); // 使用同步的getSafeBalance()保证可见性 System.out.println("The balance is : " + account1.getSafeBalance()); } }
修正后的rawWithDraw()方法
public boolean rawWithDraw(int amount) { if (balance >= amount) { // 修正判断条件 balance = balance - amount; return true; } return false; }
内容的提问来源于stack exchange,提问作者Halil Demir
相关产品推荐
相关产品推荐

