【JAVA并发编程实战】8、锁顺序死锁
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、锁顺序死锁的更多相关文章
- JAVA并发编程学习笔记------锁顺序死锁
一.需求描述: 将资金从一个账户转移到另一个账户. 二.程序实现: (1)账户类: public class Account { private long account; public Accoun ...
- java并发编程实战《五》死锁
一不小心就死锁了,怎么办? 在上一篇文章中,我们用 Account.class 作为互斥锁,来解决银行业务里面的转账问题,虽然这个方案不存在并发问题,但是所有账户的转账操作都是串行的,性能太差. 向现 ...
- Java并发编程实战(4)- 死锁
在这篇文章中,我们主要讨论一下死锁及其解决办法. 目录 概述 死锁案例 死锁的原因和预防 破坏占用且等待条件 破坏不可抢占条件 破坏循环条件 使用等待-通知机制 Java中的等待-通知机制 条件曾经满 ...
- Java并发编程实战 04死锁了怎么办?
Java并发编程文章系列 Java并发编程实战 01并发编程的Bug源头 Java并发编程实战 02Java如何解决可见性和有序性问题 Java并发编程实战 03互斥锁 解决原子性问题 前提 在第三篇 ...
- Java并发编程实战 03互斥锁 解决原子性问题
文章系列 Java并发编程实战 01并发编程的Bug源头 Java并发编程实战 02Java如何解决可见性和有序性问题 摘要 在上一篇文章02Java如何解决可见性和有序性问题当中,我们解决了可见性和 ...
- 【Java并发编程实战】----- AQS(二):获取锁、释放锁
上篇博客稍微介绍了一下AQS,下面我们来关注下AQS的所获取和锁释放. AQS锁获取 AQS包含如下几个方法: acquire(int arg):以独占模式获取对象,忽略中断. acquireInte ...
- 【Java并发编程实战】-----“J.U.C”:ReentrantReadWriteLock
ReentrantLock实现了标准的互斥操作,也就是说在某一时刻只有有一个线程持有锁.ReentrantLock采用这种独占的保守锁直接,在一定程度上减低了吞吐量.在这种情况下任何的"读/ ...
- 【Java并发编程实战】-----“J.U.C”:ReentrantLock之一简介
注:由于要介绍ReentrantLock的东西太多了,免得各位客官看累,所以分三篇博客来阐述.本篇博客介绍ReentrantLock基本内容,后两篇博客从源码级别分别阐述ReentrantLock的l ...
- Java并发编程实战 05等待-通知机制和活跃性问题
Java并发编程系列 Java并发编程实战 01并发编程的Bug源头 Java并发编程实战 02Java如何解决可见性和有序性问题 Java并发编程实战 03互斥锁 解决原子性问题 Java并发编程实 ...
- Java并发编程实战——读后感
未完待续. 阅读帮助 本文运用<如何阅读一本书>的学习方法进行学习. P15 表示对于书的第15页. Java并发编程实战简称为并发书或者该书之类的. 熟能生巧,不断地去理解,就像欣赏一部 ...
随机推荐
- PHPCMS后台密码忘记解决办法
什么是PHPCMS? PHPCMS是一款网站管理软件.该软件采用模块化开发,支持多种分类方式,使用它可方便实现个性化网站的设计.开发与维护.它支持众多的程序组合,可轻松实现网站平台迁移,并可广泛满足各 ...
- JavaWeb配置外部应用的两种方式
原来我们的项目放到webapps下,现在放到外面,也希望tomcat可以找到它!把应用放到tomcat之外,这就是外部应用了.应用已经不在tomcat中了,这时我们需要在tomcat中配置外部应用的位 ...
- salesforce 零基础学习(四十九)自定义列表分页之使用Pagination实现分页效果 ※※※
上篇内容为Pagination基类的封装,此篇接上篇内容描述如何调用Pagination基类. 首先先创建一个sObject,起名Company info,此object字段信息如下: 为了国际化考虑 ...
- KnockoutJS 3.X API 第七章 其他技术(1) 加载和保存JSON数据
Knockout允许您实现复杂的客户端交互性,但几乎所有Web应用程序还需要与服务器交换数据,或至少将本地存储的数据序列化. 最方便的交换或存储数据的方式是JSON格式 - 大多数Ajax应用程序今天 ...
- Yii2-多表关联的用法示例
本篇博客是基于<活动记录(Active Record)>中对于AR表关联用法的介绍. 我会构造一个业务场景,主要是测试我比较存疑的各种表关联写法,而非再次介绍基础用法. 构造场景 订单ar ...
- 了解Package Configurations
使用VS2010创建的SSIS Project有两种deployment model:project deployment 和 package deployment,默认是Project deploy ...
- LINQ系列:Linq to Object转换操作符
转换是指将输入对象的类型转变为序列的动作. 1. AsEnumerable AsEnumerable操作符将查询的输入以IEnumberable(T)类型返回. 2. Cast Cast操作符将IEn ...
- 【WP开发】JSON数据的读与写
在不使用其他库的情况下,WP-RT应用中也可以处理JSON数据.主要的几个类都放到Windows.Data.Json命名空间中: IJsonValue接口作为用于封装JSON数据的规范,其中只读属性V ...
- OpenCascade Chinese Text Rendering
OpenCascade Chinese Text Rendering eryar@163.com Abstract. OpenCascade uses advanced text rendering ...
- ModelDataExchange - Import
ModelDataExchange - Import eryar@163.com Abstract. The ModelDataExchange import utility enables the ...