同步

来源:互联网 发布:思迅软件合作伙伴社区 编辑:程序博客网 时间:2024/06/11 19:57

        在大多数实际的多线程应用中,两个或多个以上的线程需要共享对同一数据的存取,如果两个线程存取相同的对象,并且每个线程都调用了一个修改该对象状态的方法,将会发生线程彼此踩了对方的脚。根据各线程访问数据的次序,可能会产生讹误的对象。这样一个情况通常称为竞争条件。

        为了避免多线程引起的对共享数据的讹误,必须要做到同步存取。

        下面将模拟一个有若干账户的银行。随机地生成在这些账户之间转移钱款的交易。每一个账户有一个线程。每一笔交易中,会从线程所服务的账户中随机转移一定目的钱款到另一个随机账户。

        模拟代码很直观。我们具有transfer方法的Bank类。该方法从一个账户转移一定数目的钱款到另一个账户(还没有考虑负的账户余额)。如下是Bank类的transfer方法的代码。

public void transfer(int from, int to, double amount){if (accounts[from] < amount) return;System.out.print(Thread.currentThread());      //获取当前线程accounts[from] -= amount;System.out.printf("%10.2f from %d to %d", amount, from, to);accounts[to] += amount;System.out.printf("Total Balance: %10.2f%n", getTotalBalance());}
        下面是TransferRunnable类的代码。它的run方法不断地从一个固定的银行账户取出钱款。在每一次迭代中,run方法随机选择一个目标账户和一个随机账户,调用bank对象的transfer方法,然后睡眠。

<pre name="code" class="cpp"><pre name="code" class="java">class TransferRunnable implements Runnable{        ...        public void run(){try{while (true){int toAccount = (int) (bank.size() * Math.random());double amount = maxAmount * Math.random();bank.transfer(fromAccount, toAccount, maxAmount);Thread.sleep((int)(DELAY * Math.random()));}} catch (InterruptedException e){}}}

        当这个模拟程序运行时,不清楚在某一时刻某一银行账户中有多少钱。但是,知道所有账户的总金额应该保持不变,因为所做的一切不过是从一个账户转移钱款到另一账户。

       在每一次交易的结尾,transfer方法重新计算总值并打印出来。

       具体实现代码如下:

public class Bank {private final double[] accounts;public Bank(int n, double initialBalance)           //构造函数{accounts = new double[n];for (int i = 0; i < accounts.length; i++)accounts[i] = initialBalance;}public void transfer(int from, int to, double amount){if (accounts[from] < amount) return;System.out.print(Thread.currentThread());      //获取当前线程accounts[from] -= amount;System.out.printf("%10.2f from %d to %d", amount, from, to);accounts[to] += amount;System.out.printf("Total Balance: %10.2f%n", getTotalBalance());}public double getTotalBalance(){double sum = 0;for (double a : accounts)sum += a;return sum;}public int size(){return accounts.length;}}
</pre><pre name="code" class="java">public class TransferRunnable implements Runnable{private Bank bank;private int fromAccount;private double maxAmount;private int DELAY = 10;public TransferRunnable(Bank b, int from, double max){bank = b;fromAccount = from;maxAmount = max;}public void run(){try{while (true){int toAccount = (int) (bank.size() * Math.random());double amount = maxAmount * Math.random();bank.transfer(fromAccount, toAccount, maxAmount);Thread.sleep((int)(DELAY * Math.random()));}} catch (InterruptedException e){}}}
public class UnsynchTest {public static final int NACCOUNTS = 100;public static final double INITIAL_BALANCE = 1000;public static void main(String[] args) {Bank b = new Bank(NACCOUNTS, INITIAL_BALANCE);int i;for (i = 0; i < NACCOUNTS; i++){TransferRunnable r = new TransferRunnable(b, i, INITIAL_BALANCE);Thread t = new Thread(r);t.start();}}}




0 0
原创粉丝点击