从头认识java-17.4 详解同步(1)-由竞争条件引发的问题

这一章节我们来讨论一些同步的一些话题,由竞争条件引发的问题。

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元

运行了一段时间之后大家会看见,总数少了,这就是因为上面的竞争条件的出现,而且没有做数据同步而形成的。

总结:这一章节主要介绍由竞争条件引发的问题。

这一章节就到这里,谢谢。

-----------------------------------

目录

时间: 2024-10-28 20:26:27

从头认识java-17.4 详解同步(1)-由竞争条件引发的问题的相关文章

Java设计模式----观察者模式详解

[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/3899208.html 联系方式:[email protected] [正文] 一.观察者模式的定义: 简单地说,观察者模式定义了一个一对多的依赖关系,让一个或多个观察者对象监听一个主题对象.这样一来,当被观察者状态发生改变时,需要通知相应的观察者,使这些观察者对象能够自动更新.例如:GUI中的事件

Java关键字synchronized详解

Java关键字synchronized详解 博客分类: Java综合 Java多线程thread互联网制造 synchronized 关键字,代表这个方法加锁,相当于不管哪一个线程A每次运行到这个方法时,都要检查有没有其它正在用这个方法的线程B(或者C D等),有的话要等正在使用这个方法的线程B(或者C D)运行完这个方法后再运行此线程A,没有的话,直接运行 它包括两种用法:synchronized 方法和 synchronized 块. 1. synchronized 方法: 通过在方法声明中

转:Java HashMap实现详解

Java HashMap实现详解 转:http://beyond99.blog.51cto.com/1469451/429789 1.    HashMap概述: HashMap是基于哈希表的Map接口的非同步实现.此实现提供所有可选的映射操作,并允许使用null值和null键.此类不保证映射的顺序,特别是它不保证该顺序恒久不变. 2.    HashMap的数据结构: 在java编程语言中,最基本的结构就是两种,一个是数组,另外一个是模拟指针(引用),所有的数据结构都可以用这两个基本结构来构造

【转】 java中HashMap详解

原文网址:http://blog.csdn.net/caihaijiang/article/details/6280251 java中HashMap详解 HashMap 和 HashSet 是 Java Collection Framework 的两个重要成员,其中 HashMap 是 Map 接口的常用实现类,HashSet 是 Set 接口的常用实现类.虽然 HashMap 和 HashSet 实现的接口规范不同,但它们底层的 Hash 存储机制完全一样,甚至 HashSet 本身就采用 H

java UDP传输详解

UDP传输是一个面向无连接的传输方式,什么叫无连接呢,简单点说呢就是不管你在不在线,我都发数据给你,像那个电影里警察拿的那个呼叫用的就这这个原理 还有以前的QQ聊天也是,现在2013版的可以选择是UPD还是TCP,好了不多说,上点代码玩一下 分析:通过udp传输方式,将一段数据发送出去 思路: 1,建议udpsocket服务 2,提供数据,并将数据封装到数据包中 3,通过socket服务的发送功能,讲数据包发送出去. 4,关闭资源 牢记思路,代码哪里都有 package com.szc02; i

AJAX请求详解 同步异步 GET和POST

AJAX请求详解 同步异步 GET和POST 上一篇博文(http://www.cnblogs.com/mengdd/p/4191941.html)介绍了AJAX的概念和基本使用,附有一个小例子,下面基于这个例子做一些探讨. 同步和异步 在准备请求的时候,我们给open方法里传入了几个参数,其中第三个参数为true时,表示是异步请求: //1. prepare request xmlHttpRequest.open("GET", "AjaxServlet", tru

Java多线程编程详解

线程的同步 由于同一进程的多个线程共享同一片存储空间,在带来方便的同时,也带来了访问冲突这个严重的问题.Java语言提供了专门机制以解决这种冲突,有效避免了同一个数据对象被多个线程同时访问. 由于我们可以通过 private 关键字来保证数据对象只能被方法访问,所以我们只需针对方法提出一套机制,这套机制就是 synchronized 关键字,它包括两种用法:synchronized 方法和 synchronized 块. 1. synchronized 方法:通过在方法声明中加入 synch

java 序列化Serializable 详解

Java 序列化Serializable详解(附详细例子) 1.什么是序列化和反序列化Serialization(序列化)是一种将对象以一连串的字节描述的过程:反序列化deserialization是一种将这些字节重建成一个对象的过程.   2.什么情况下需要序列化 a)当你想把的内存中的对象保存到一个文件中或者数据库中时候:b)当你想用套接字在网络上传送对象的时候:c)当你想通过RMI传输对象的时候: 3.如何实现序列化 将需要序列化的类实现Serializable接口就可以了,Seriali

最新java数组的详解

java中HashMap详解 http://alex09.iteye.com/blog/539545 总结: 1.就像引用类型的数组一样,当我们把 Java 对象放入数组之时,并不是真正的把 Java 对象放入数组中,只是把对象的引用放入数组中,每个数组元素都是一个引用变量. 2.HashMap 采用一种所谓的“Hash 算法”来决定每个元素的存储位置. 3.HashMap 底层采用一个 Entry[] 数组来保存所有的 key-value 对,当需要存储一个 Entry 对象时,会根据 Has