package player.kent.chen.learn.reorder; import java.text.MessageFormat; //转账类 public class Transfer { private int amountA = 100; private int amountB = 100; private volatile boolean committed; //转账动作 public void doTransfer() { amountA = amountA - 50; amountB = amountB + 50; committed = true; } //转账结束时打印两个账户的值 public void printAccountsWhenDone() { if(!committed) { //转账未结束则等待。 return; } System.out.println(MessageFormat.format("amountA = {0}, amountB = {1}", amountA, amountB)); } public static void main(String[] args) { final Transfer transfer = new Transfer(); Thread t1 = new Thread(new Runnable() { public void run() { transfer.doTransfer(); } }); Thread t2 = new Thread(new Runnable() { public void run() { while(true){ transfer.printAccountsWhenDone(); } } }); t2.start(); //线程2等转账结束后打印账户节余 t1.start(); //线程1处理转账 } }
最后打印的账户节余是多少?
初看应该是 A = 50 和 B = 100.
可是,按指令重排原理, 下面三句话可能被CPU按别的顺序执行:
amountA = amountA - 50; amountB = amountB + 50; committed = true;
比如,可能重排成
amountA = amountA - 50; committed = true; amountB = amountB + 50;
这时候打印出来的值可能就是 A = 50, B = 100 .
要解决这个问题,就要给doTransfer()和printAccountsWhenDone()都加上synchronized关键字,当t1执行doTransfer时t2必须等待,等t1执行完后t2再去获取A和B的值,即使doTransfer()内部有指令重排,也不会有问题。