这一章节我们来讨论一些同步的一些话题,由竞争条件引发的问题。
1.什么是竞争条件?
多个线程或者进程在读写一个共享数据时结果依赖于它们执行的相对时间,这种情形叫做竞争。
竞争条件发生在当多个进程或者线程在读写数据时,其最终的的结果依赖于多个进程的指令执行顺序。
举一个例子:
我们平常编程经常遇到的修改某个字段,这个操作在库存那里尤为突出,当两个单子同时修改库存的时候,这时就形成了竞争条件,如果不做同步处理,这里十有八九就是错误的了,因为如果两个单子同时出库,而出库的数量刚好大于库存数量,这里就会出现问题。(当然,还有几种情况会出现问题,我们这里只是为了举一个竞争条件的例子)
2.我们下面以一个我们之前提到过的银行转账的例子为例来说明这个问题。
我们建立3各类:
package com.ray.ch17; public class Bank { private final double[] accounts; public double[] getAccounts() { return accounts; } public Bank(int n, double initBalance) { accounts = new double[n]; for (int i = 0; i < accounts.length; i++) { accounts[i] = initBalance; } } public double getTotal() { double total = 0; for (int i = 0; i < accounts.length; i++) { total += accounts[i]; } return total; } public void transfer(int fromAccount, int toAccount, double money) { if (accounts[fromAccount] < money) { return; } accounts[fromAccount] -= money; System.out.printf("从" + fromAccount + "账户转出%10.2f元,", money); accounts[toAccount] += money; System.out.printf("从" + toAccount + "账户转入%10.2f元,", money); System.out.printf("总数:%10.2f元", getTotal()); System.out.println(); } public int size() { return accounts.length; } }
package com.ray.ch17; import java.util.Random; public class TransferThread implements Runnable { private Bank bank; private final double MAX; public TransferThread(Bank bank, double max) { this.bank = bank; this.MAX = max; } @Override public void run() { while (true) { double amount = MAX * Math.random(); int countOfAccount = bank.getAccounts().length; bank.transfer(new Random().nextInt(countOfAccount), new Random().nextInt(countOfAccount), amount); } } }
package com.ray.ch17; public class Test { public static void main(String[] args) { Bank bank = new Bank(100, 10000); for (int i = 0; i < 20; i++) { TransferThread transferThread = new TransferThread(bank, 10000); Thread thread = new Thread(transferThread); thread.start(); } } }
输出:
从34账户转出 8175.29元,从39账户转入 8175.29元,总数:1000000.00元
从16账户转出 165.66元,从88账户转入 165.66元,总数:1000000.00元
从19账户转出 3604.29元,从72账户转入 3604.29元,总数:1000000.00元
从5账户转出 3153.76元,从41账户转入 3153.76元,总数:1000000.00元
从91账户转出 1176.97元,从32账户转入 1176.97元,总数:1000000.00元
......
从7账户转出 8817.14元,从32账户转入 8817.14元,总数: 929031.75元
从62账户转出 2491.59元,从90账户转入 2491.59元,总数: 927085.68元
从45账户转出 5800.54元,从69账户转入 5800.54元,总数: 927085.68元
从74账户转出 1570.19元,从17账户转入 1570.19元,总数: 926108.26元
从83账户转出 2550.74元,从9账户转入 2550.74元,总数: 926108.26元
从3账户转出 4207.99元,从73账户转入 4207.99元,总数: 924953.29元
从11账户转出 6369.35元,从38账户转入 6369.35元,总数: 924572.99元
运行了一段时间之后大家会看见,总数少了,这就是因为上面的竞争条件的出现,而且没有做数据同步而形成的。
总结:这一章节主要介绍由竞争条件引发的问题。
这一章节就到这里,谢谢。
-----------------------------------