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()内部有指令重排,也不会有问题。