从头认识java-17.4 详解同步(5)- 死锁

这一章节我们来简单讨论一下死锁,其实死锁是一个比较大的话题,但是我这里只是根据我前面的银行转账的例子来说明,在后面会有详细的专栏来说明并发编程的各个方面的问题。

1.什么是死锁?

是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。

2.怎样会引起死锁?

(1) 互斥条件:一个资源每次只能被一个进程使用;

(2) 请求与保持条件:既拿着现有资源,又去申请其他资源,但申请不上一直被阻塞;

(3) 不剥夺条件:不能够通过优先级来剥夺资源使用权的资源;

(4) 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

3.我们前面的例子是怎样引起死锁的?

(1)死锁产生的过程:

账号1原有200元
账号2原有300元
线程1:从账户1转300元到账户2 
线程2:从账户2转400元到账户1

(2)引起死锁的代码块:

public void transfer(int fromAccount, int toAccount, double money) {
		if (accounts[fromAccount] < money) {
			System.out.println(Thread.currentThread().getName() + "出现死锁");
			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();
	}

(3)原因:

当转账的钱大于现有的余额,将会产生死锁

(4)解决方案:

但是由于现实业务不允许这种情况出现,因此我们直接return就解决了死锁的问题。

(5)如果是其他多线程竞争资源,里面不是像上面一样的return,而且等待,就会出现死锁的情况。

4.完整例子:

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) {
			System.out.println(Thread.currentThread().getName() + "出现死锁");
			// Thread.currentThread().wait();//如果是其他的多线程,可能在这里是wait,从而出现真正的死锁
			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 < 2; i++) {
			TransferThread transferThread = new TransferThread(bank, 10000);
			Thread thread = new Thread(transferThread);
			thread.start();
		}
	}
}

总结:这一章节简单介绍了死锁。

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

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

目录

时间: 2024-11-02 23:30:20

从头认识java-17.4 详解同步(5)- 死锁的相关文章

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

Java 序列化Serializable详解

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