package cn.study.concurrency.ch10;

public class Account {
private String staffAccount; //账号
private String passWord; //密码
private int balance; //账户余额 public Account(int money) {
this.balance = money;
} public String getStaffAccount() {
return staffAccount;
}
public void setStaffAccount(String staffAccount) {
this.staffAccount = staffAccount;
}
public String getPassWord() {
return passWord;
}
public void setPassWord(String passWord) {
this.passWord = passWord;
} public void debit(int amount)
{
System.out.println("转出账户:" + amount);
} public void credit(int amount)
{
System.out.println("转入账户:" + amount);
}
public int getBalance() {
return balance;
}
public void setBalance(int balance) {
this.balance = balance;
} }
package cn.study.concurrency.ch10;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import javax.naming.InsufficientResourcesException; /**
* 通过制定确定的锁顺序来避免死锁
* @author xiaof
*
*/
public class DeathLock {
public void transferMoney(Account fromAccount, Account toAccount, int amount) throws InsufficientResourcesException
{
synchronized(fromAccount)
{
synchronized(toAccount)
{
//按参数的顺序上锁,这个依据参数的调用方法的顺序
if(fromAccount.getBalance() < amount)
{
//账户余额不足,无法转账
throw new InsufficientResourcesException();
}
else
{
fromAccount.debit(amount);
toAccount.credit(amount);
}
}
}
}
/**
* 这个用来在无法判定枷锁顺序的时候的加时赛锁
*/
private static final Object tieLock = new Object(); public static void transferMoney2(final Account fromAccount, final Account toAccount, final int amount) throws InsufficientResourcesException
{
/**
* 辅助内部类
* @author xiaof
*
*/
class Helper
{
public void transfer() throws InsufficientResourcesException
{
//内部类可以随意访问外部类成员
//按参数的顺序上锁,这个依据参数的调用方法的顺序
if(fromAccount.getBalance() < amount)
{
//账户余额不足,无法转账
throw new InsufficientResourcesException();
}
else
{
fromAccount.debit(amount);
toAccount.credit(amount);
}
}
}
//返回给定对象的哈希码,该代码与默认的方法 hashCode() 返回的代码一样,无论给定对象的类是否重写 hashCode()
int fromHash = System.identityHashCode(fromAccount);
int toHash = System.identityHashCode(toAccount);
//根据hash值判定加锁顺序,那么一样的对象的锁顺序就一定一样
if(fromHash < toHash)
{
synchronized(fromAccount)
{
synchronized(toAccount)
{
new Helper().transfer();
}
}
}
else if(toHash < fromHash)
{
synchronized(toAccount)
{
synchronized(fromAccount)
{
new Helper().transfer();
}
}
}
else
{
//如果很不巧,hash值是一样的,那么就需要一个加时赛的机制,先获取外部锁,然后再此基础上对两个对象随机上锁
synchronized(tieLock)
{
synchronized(fromAccount)
{
synchronized(toAccount)
{
new Helper().transfer();
}
}
}
} } static Account account1 = new Account(999);
static Account account2 = new Account(999); public static void main(String[] args) throws InsufficientResourcesException {
//对于第一个方法很容易死锁
//比如:当有两个同时执行这个方法的调用时候
// DeathLock dl = new DeathLock();
//这个时候第一个调用在锁了account1,然后第二个调用锁了account2
//同时第一个需要account2,第二个需要account1,这就发生竞争死锁了
// dl.transferMoney(account1, account2, 998);
// dl.transferMoney(account2, account1, 998);
//
// dl.transferMoney2(account1, account2, 998);
ExecutorService pool = Executors.newFixedThreadPool(10);
for(int i = 0; i < 5; ++ i)
{
pool.execute(new Runnable() {
@Override
public void run() {
try {
DeathLock.transferMoney2(account1, account2, 998);
} catch (InsufficientResourcesException e) {
e.printStackTrace();
}
}
});
} for(int i = 0; i < 5; ++ i)
{
pool.execute(new Runnable() {
@Override
public void run() {
try {
DeathLock.transferMoney2(account2, account1, 998);
} catch (InsufficientResourcesException e) {
e.printStackTrace();
}
}
});
} pool.shutdown();
}
}

测试结果:

【JAVA并发编程实战】8、锁顺序死锁的更多相关文章

  1. JAVA并发编程学习笔记------锁顺序死锁

    一.需求描述: 将资金从一个账户转移到另一个账户. 二.程序实现: (1)账户类: public class Account { private long account; public Accoun ...

  2. java并发编程实战《五》死锁

    一不小心就死锁了,怎么办? 在上一篇文章中,我们用 Account.class 作为互斥锁,来解决银行业务里面的转账问题,虽然这个方案不存在并发问题,但是所有账户的转账操作都是串行的,性能太差. 向现 ...

  3. Java并发编程实战(4)- 死锁

    在这篇文章中,我们主要讨论一下死锁及其解决办法. 目录 概述 死锁案例 死锁的原因和预防 破坏占用且等待条件 破坏不可抢占条件 破坏循环条件 使用等待-通知机制 Java中的等待-通知机制 条件曾经满 ...

  4. Java并发编程实战 04死锁了怎么办?

    Java并发编程文章系列 Java并发编程实战 01并发编程的Bug源头 Java并发编程实战 02Java如何解决可见性和有序性问题 Java并发编程实战 03互斥锁 解决原子性问题 前提 在第三篇 ...

  5. Java并发编程实战 03互斥锁 解决原子性问题

    文章系列 Java并发编程实战 01并发编程的Bug源头 Java并发编程实战 02Java如何解决可见性和有序性问题 摘要 在上一篇文章02Java如何解决可见性和有序性问题当中,我们解决了可见性和 ...

  6. 【Java并发编程实战】----- AQS(二):获取锁、释放锁

    上篇博客稍微介绍了一下AQS,下面我们来关注下AQS的所获取和锁释放. AQS锁获取 AQS包含如下几个方法: acquire(int arg):以独占模式获取对象,忽略中断. acquireInte ...

  7. 【Java并发编程实战】-----“J.U.C”:ReentrantReadWriteLock

    ReentrantLock实现了标准的互斥操作,也就是说在某一时刻只有有一个线程持有锁.ReentrantLock采用这种独占的保守锁直接,在一定程度上减低了吞吐量.在这种情况下任何的"读/ ...

  8. 【Java并发编程实战】-----“J.U.C”:ReentrantLock之一简介

    注:由于要介绍ReentrantLock的东西太多了,免得各位客官看累,所以分三篇博客来阐述.本篇博客介绍ReentrantLock基本内容,后两篇博客从源码级别分别阐述ReentrantLock的l ...

  9. Java并发编程实战 05等待-通知机制和活跃性问题

    Java并发编程系列 Java并发编程实战 01并发编程的Bug源头 Java并发编程实战 02Java如何解决可见性和有序性问题 Java并发编程实战 03互斥锁 解决原子性问题 Java并发编程实 ...

  10. Java并发编程实战——读后感

    未完待续. 阅读帮助 本文运用<如何阅读一本书>的学习方法进行学习. P15 表示对于书的第15页. Java并发编程实战简称为并发书或者该书之类的. 熟能生巧,不断地去理解,就像欣赏一部 ...

随机推荐

  1. Windows Azure Storage (6) Windows Azure Storage之Table

    <Windows Azure Platform 系列文章目录> 最近想了想,还是有必要把Windows Azure Table Storage 给说清楚. 1.概念 Windows Azu ...

  2. Servlet程序中玩验证码

    验证码思想:所谓验证码就是产生若干随机数,存放到session中,然后在servlet中获取session中的该值与页面输入值相比较,进而判断正误.   产生验证码的方法: 随机数放在图片中,封装为一 ...

  3. Eclipse启动参数

    from 网络 eclipse 启动参数 -clean2013-- : eclipse 启动参数介绍(如添加插件时,如果不显示,则使用eclipse -clean启动) 其实,Eclipse是一个可以 ...

  4. Struts2学习笔记 - Action篇<定义逻辑Action>

    有三种方法可以使一个Action处理多个请求 动态方法调用DMI 定义逻辑Acton 在配置文件中使用通配符 这文章就谈论一下定义逻辑Action 这里主要关注的是struts.xml配置文件,一般情 ...

  5. IM消息送达保证机制实现(二):保证离线消息的可靠投递

    1.前言 本文的上篇<IM消息送达保证机制实现(一):保证在线实时消息的可靠投递>中,我们讨论了在线实时消息的投递可以通过应用层的确认.发送方的超时重传.接收方的去重等手段来保证业务层面消 ...

  6. Sql Server系列:排序函数

    在SQL Server中有4个排序函数:ROW_NUMBER().RANK().DENSE_RANK()及NTILE()函数. 1. ROW_NUMBER()函数 ROW_NUMBER()函数为每条记 ...

  7. 网络连接详细信息出现两个自动配置ipv4地址

    问题:网络连接详细信息出现两个自动配置ipv4地址,一个是有效地址,一个是无效地址. 解决办法:先将本地连接ip设置成自动获取,然后点击开始——>运行——>输入cmd,回车,进入命令行界面 ...

  8. Android 如何制作九宫格图片(.9.png)

    对于编程人员来说,尤其是前端设计设计师,九宫格图片是必须的(.9.png),对于初学者来说不知道这个九宫格图片有什么用,其实这个九宫格图片实际常用在Android的button组件.要上下拉升的背景图 ...

  9. c/c++多线程模拟系统资源分配(并通过银行家算法避免死锁产生)

    银行家算法数据结构 (1)可利用资源向量Available 是个含有m个元素的数组,其中的每一个元素代表一类可利用的资源数目.如果Available[j]=K,则表示系统中现有Rj类资源K个. (2) ...

  10. Power BI官方视频(1) Power BI Desktop 7月份更新功能概述

    2016年7月,Power BI Desktop进行了一些功能更新,提高整体的用户体验.同时也有一些新的和令人兴奋的功能.看看大概介绍,更新功能要点: 本文原文地址:Power BI官方视频(1) P ...