Java并发编程实战系列10之避免活跃性危险
10.1 死锁
哲学家问题
有环
A等B,B等A
数据库往往可以检测和解决死锁//TODO
JVM不行,一旦死锁只有停止重启。
下面分别介绍了几种典型的死锁情况:
10.1.1 Lock ordering Deadlocks
下面是一个经典的锁顺序死锁:两个线程用不同的顺序来获得相同的锁,如果按照锁的请求顺序来请求锁,就不会发生这种循环依赖的情况。
public class LeftRightDeadlock {private final Object left = new Object();private final Object right = new Object();public void leftRight() {synchronized (left) {synchronized (right) {doSomething();}}}public void rightLeft() {synchronized (right) {synchronized (left) {doSomethingElse();}}}void doSomething() {}void doSomethingElse() {}
}
10.1.1 Dynamic Lock Order Deadlocks
下面的转账例子,如果一个线程X向Y转,而另外一个线程Y向X也转,那么就会发生死锁。
public class DynamicOrderDeadlock {// Warning: deadlock-prone!public static void transferMoney(Account fromAccount,Account toAccount,DollarAmount amount)throws InsufficientFundsException {synchronized (fromAccount) {synchronized (toAccount) {if (fromAccount.getBalance().compareTo(amount) < 0)throw new InsufficientFundsException();else {fromAccount.debit(amount);toAccount.credit(amount);}}}}static class DollarAmount implements Comparable<DollarAmount> {// Needs implementationpublic DollarAmount(int amount) {}public DollarAmount add(DollarAmount d) {return null;}public DollarAmount subtract(DollarAmount d) {return null;}public int compareTo(DollarAmount dollarAmount) {return 0;}}static class Account {private DollarAmount balance;private final int acctNo;private static final AtomicInteger sequence = new AtomicInteger();public Account() {acctNo = sequence.incrementAndGet();}void debit(DollarAmount d) {balance = balance.subtract(d);}void credit(DollarAmount d) {balance = balance.add(d);}DollarAmount getBalance() {return balance;}int getAcctNo() {return acctNo;}}static class InsufficientFundsException extends Exception {}
}
解决办法还是顺序话锁,考虑针对两种情况取hashcode然后判断if-else里面决定锁顺序。
class Helper {public void transfer() throws InsufficientFundsException {if (fromAcct.getBalance().compareTo(amount) < 0)throw new InsufficientFundsException();else {fromAcct.debit(amount);toAcct.credit(amount);}}}int fromHash = System.identityHashCode(fromAcct);int toHash = System.identityHashCode(toAcct);if (fromHash < toHash) {synchronized (fromAcct) {synchronized (toAcct) {new Helper().transfer();}}} else if (fromHash > toHash) {synchronized (toAcct) {synchronized (fromAcct) {new Helper().transfer();}}} else {synchronized (tieLock) {synchronized (fromAcct) {synchronized (toAcct) {new Helper().transfer();}}}}
10.1.3 在协作对象之间发生死锁Deadlocks Between Cooperating Objects
下面的例子setLocation和getImage都会获取两把锁,会存在两个线程按照不同的顺序获取锁的情况。
public class CooperatingDeadlock {// Warning: deadlock-prone!class Taxi {@GuardedBy("this") private Point location, destination;private final Dispatcher dispatcher;public Taxi(Dispatcher dispatcher) {this.dispatcher = dispatcher;}public synchronized Point getLocation() {return location;}public synchronized void setLocation(Point location) {this.location = location;if (location.equals(destination))dispatcher.notifyAvailable(this);}public synchronized Point getDestination() {return destination;}public synchronized void setDestination(Point destination) {this.destination = destination;}}class Dispatcher {@GuardedBy("this") private final Set<Taxi> taxis;@GuardedBy("this") private final Set<Taxi> availableTaxis;public Dispatcher() {taxis = new HashSet<Taxi>();availableTaxis = new HashSet<Taxi>();}public synchronized void notifyAvailable(Taxi taxi) {availableTaxis.add(taxi);}public synchronized Image getImage() {Image image = new Image();for (Taxi t : taxis)image.drawMarker(t.getLocation());return image;}}class Image {public void drawMarker(Point p) {}}
}
10.1.4 开放调用
减小锁的力度,锁不嵌套。
class CooperatingNoDeadlock {@ThreadSafeclass Taxi {@GuardedBy("this") private Point location, destination;private final Dispatcher dispatcher;public Taxi(Dispatcher dispatcher) {this.dispatcher = dispatcher;}public synchronized Point getLocation() {return location;}public synchronized void setLocation(Point location) {boolean reachedDestination;synchronized (this) {this.location = location;reachedDestination = location.equals(destination);}if (reachedDestination)dispatcher.notifyAvailable(this);}public synchronized Point getDestination() {return destination;}public synchronized void setDestination(Point destination) {this.destination = destination;}}@ThreadSafeclass Dispatcher {@GuardedBy("this") private final Set<Taxi> taxis;@GuardedBy("this") private final Set<Taxi> availableTaxis;public Dispatcher() {taxis = new HashSet<Taxi>();availableTaxis = new HashSet<Taxi>();}public synchronized void notifyAvailable(Taxi taxi) {availableTaxis.add(taxi);}public Image getImage() {Set<Taxi> copy;synchronized (this) {copy = new HashSet<Taxi>(taxis);}Image image = new Image();for (Taxi t : copy)image.drawMarker(t.getLocation());return image;}}class Image {public void drawMarker(Point p) {}}}
1.0.15 资源死锁
- 数据库连接池,A持有数据库D1连接,等待与D2连接,B持有D2的连接,等待与D1连接。
- 线程饥饿死锁,如8.1.1小节的例子。
10.2 死锁的避免与诊断
10.2.1 支持定时的锁
tryLock
10.2.2 kill -3 发信号给JVM dump线程
10.3 其他活跃性危险
10.3.1 饥饿
10.3.3 活锁Livelock
他不会阻塞线程,但是也不能继续执行,因为线程在不断的重复执行相同的操作,而且总会失败。
例如处理事务消,回滚后再次重新把任务放在队头。
又例如发送数据包,都选择1s后重试,那么总会冲突,所以可以考虑一个随机数时间间隔。
Java并发编程实战系列10之避免活跃性危险相关推荐
- 《Java并发编程实战》第十章 避免活跃性危急 读书笔记
一.死锁 所谓死锁: 是指两个或两个以上的进程在运行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去. 百科百科 当两个以上的运算单元,两方都在等待对方停止执行,以取得 ...
- Java并发编程实战系列15之原子遍历与非阻塞同步机制(Atomic Variables and Non-blocking Synchronization)...
近年来,在并发算法领域的大多数研究都侧重于非阻塞算法,这种算法用底层的原子机器指令来代替锁来确保数据在并发访问中的一致性,非阻塞算法被广泛应用于OS和JVM中实现线程/进程调度机制和GC以及锁,并发数 ...
- 《Java 并发编程实战》--读书笔记
Java 并发编程实战 注: 极客时间<Java 并发编程实战>–读书笔记 GitHub:https://github.com/ByrsH/Reading-notes/blob/maste ...
- java 多线程缓存_[Java教程]【JAVA并发编程实战】12、使用condition实现多线程下的有界缓存先进先出队列...
[Java教程][JAVA并发编程实战]12.使用condition实现多线程下的有界缓存先进先出队列 0 2016-11-29 17:00:10 package cn.study.concurren ...
- Java并发编程实战————恢复中断
中断是一种协作机制,一个线程不能强制其他线程停止正在执行的操作而去执行其他操作. 什么是中断状态? 线程类有一个描述自身是否被中断了的boolean类型的状态,可以通过调用 .isInterrupte ...
- Java并发编程实战————Executor框架与任务执行
引言 本篇博客介绍通过"执行任务"的机制来设计应用程序时需要掌握的一些知识.所有的内容均提炼自<Java并发编程实战>中第六章的内容. 大多数并发应用程序都是围绕&qu ...
- Java并发编程实战————Semaphore信号量的使用浅析
引言 本篇博客讲解<Java并发编程实战>中的同步工具类:信号量 的使用和理解. 从概念.含义入手,突出重点,配以代码实例及讲解,并以生活中的案例做类比加强记忆. 什么是信号量 Java中 ...
- Java并发编程实战_不愧是领军人物!这种等级的“Java并发编程宝典”谁能撰写?...
前言 大家都知道并发编程技术就是在同一个处理器上同时的去处理多个任务,充分的利用到处理器的每个核心,最大化的发挥处理器的峰值性能,这样就可以避免我们因为性能而产生的一些问题. 大厂的核心负载肯定是非常 ...
- java单线程共享,「Java并发编程实战」之对象的共享
前言 本系列博客是对<Java并发编程实战>的一点总结,本篇主要讲解以下几个内容,内容会比较枯燥.可能大家看标题不能能直观的感受出到底什么意思,这就是专业术语,哈哈,解释下,术语(term ...
最新文章
- 点击某个a标签,禁止页面自动跳转到该页面的顶部
- html中怎么设置文本框居中显示图片,css如何让图片水平居中显示?
- java 程序架构知识
- 客户端手册_山东省税务局社保费管理客户端企业缴费操作手册
- tableau必知必会之轻松搞定 关系网 图表
- 文件移到废纸篓,可是这个状态就卡住了
- 手写自己的MyBatis框架-Executor
- python 获取当前文件夹下所有文件名
- java 强制向上转型,Java 转型(向上或向下转型)详解及简单实例
- 假如地球变成甜甜圈形状,世界会变成什么样子?
- 自媒体公约:良性发展大于利益本能
- 2011.11.2 try
- WINDOWS也需要装WINDOWS虚拟机
- 不保留小数php,php怎么实现不保留小数
- idea打包 jar文件
- PTAM特征点法跟踪和建图 SLAM FAST Patch
- PS修改图片的背景颜色(无需抠图)
- IP和网段的计算方法
- 数学术语的英汉对照(权威,全面)
- Unity内实现MMD
热门文章
- 伊利诺伊大学厄巴纳-香槟分校
- windows 64位 dll文件 位置及python包rtree shapely安装
- Redis 系统学习目录
- stat用法:获取文件对应权限的数字
- 最新CAX/EDA/CFD/GIS/光学/化工/液压软件资源网
- Java集合工具类(三)-泛型集合工具类,用于便捷快速的定义、操作集合。包含Set的交集、并集......
- 《Python从小白到大牛》第6章 数据类型
- Linux vim使用心得III
- U-Mail邮件系统带您体验微信收发邮件
- 《Git in Practice》作者访谈:关于Git的八个问题