码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2016-01-15 13:03:23      阅读:185      评论:0      收藏:0      [点我收藏+]

标签:

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

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();
		}
	}
}


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


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

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

目录



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

标签:

原文地址:http://blog.csdn.net/raylee2007/article/details/50522546

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!