同步
来源:互联网 发布:思迅软件合作伙伴社区 编辑:程序博客网 时间: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
- 同步
- 同步
- 同步
- 同步
- 同步
- 同步
- 同步
- 同步
- 同步
- 同步
- 同步
- 同步
- 同步
- 同步
- 同步
- 同步
- 同步
- 同步
- 设计模式 (3)用例图之二
- onAnimationEnd不一定能执行
- ssh 证书方式远程登陆linux主机
- WebLogic、WebSphere、JBOSS、Tomcat之间的区别 2
- “浪潮杯”山东省赛 sdut 3256 BIGZHUGOD and His Friends II
- 同步
- POJ1287 Networking(最小生成树)
- flex&&bison
- 一个Android图片(视频)选择器:android-media-picker
- Java动态代理
- HDU 1012 u Calculate e
- 飛飛(十七)用递归方法求a!
- 7 面向对象(成员变量和局部变量的区别,类作为形式参数的问题,匿名对象,封装,private关键字,this关键字,构造方法,类的初始化过程,static关键字)
- 线性表顺序存储结构实现