Java学习day092 并发(四)(同步(一):竞争条件的一个例子、竞争条件详解、锁对象、条件对象)

本文探讨了Java中的并发问题,通过银行账户转账的模拟程序展示了竞争条件,即多个线程同时访问同一数据导致的错误。介绍了同步的重要性,通过`synchronized`关键字和`ReentrantLock`类来防止并发访问的干扰。锁对象确保同一时间只有一个线程执行特定代码块,条件对象则用于管理因条件未满足而需等待的线程,确保线程安全地协同工作。
摘要由CSDN通过智能技术生成

使用的教材是java核心技术卷1,我将跟着这本书的章节同时配合视频资源来进行学习基础java知识。

day092   并发(四)(同步(一):竞争条件的一个例子、竞争条件详解、锁对象、条件对象)


同步

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


1.竞争条件的一个例子

为了避免多线程引起的对共享数据的说误,必须学习如何同步存取。在本节中,你会看到如果没有使用同步会发生什么。在下一节中,将会看到如何同步数据存取。

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

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

public void transfer(int from, int to, double amount)
	{
		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());
	}

这里是Runnable类的代码。它的run方法不断地从一个固定的银行账户取出钱款。在每一次迭代中,run方法随机选择一个目标账户和一个随机账户,调用bank对象的transfer方法,然后睡眠。

Runnable r = () -> {
				try
				{
					while(true)
					{
						int toAccount = (int) (bank.size() * Math.random());
						double amount = MAX_AMOUNT * Math.random();
						bank.transfer(fromAccount, toAccount, amount);
						Thread.sleep((int) (DELAY * Math.random()));
					}
				}
				catch(InterruptedException e)
				{
				}
			};

当这个模拟程序运行时,不清楚在某一时刻某一银行账户中有多少钱。但是,知道所有账户的总金额应该保持不变,因为所做的一切不过是从一个账户转移钱款到另一个账户。在每一次交易的结尾,transfer方法重新计算总值并打印出来。本程序永远不会结束。只能按CTRL+C来终止这个程序。

出现了错误。在最初的交易中,银行的余额保持在$100000,这是正确的,因为共100个账户,每个账户$1000。但是,过一段时间,余额总量有轻微的变化。当运行这个程序的时候,会发现有时很快就出错了,有时很长的时间后余额发生混乱。这样的状态不会带来信任感,人们很可能不愿意将辛苦挣来的钱存到这个银行。

下面是代码:

/**
 *@author  zzehao
 *This program shows data corruption when multiple threads access a data structure.
 */

public class UnsynchBankTest
{
	public static final int NACCOUNTS = 100;
	public static final double INITIAL_BALANCE = 1000;
	public static final double MAX_AMOUNT = 1000;
	public static final int DELAY = 10;
	
	public static void main(String[]
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值