同步

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

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

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

        模拟代码很直观。我们具有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();
		}
	}
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值