《Java并发编程实战》第十章 避免活跃性危急 读书笔记
2023-09-14 09:06:24 时间
一、死锁
所谓死锁: 是指两个或两个以上的进程在运行过程中。因争夺资源而造成的一种互相等待的现象。若无外力作用。它们都将无法推进下去。
1. 顺序死锁
最少有两个锁。一个线程获取到A锁须要获取B锁才干进行操作,而另外一个线程获取到了B锁。须要获取A锁才干运行操作。这样的情况下easy出现顺序死锁。
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) { // doSomething(); } } } }
2. 动态的锁顺序死锁
public void transferMoney(Account fromAccount, Account toAccount, DollarAmount anount) throws InsufficientResourcesException { synchronized (fromAccount) { synchronized (toAccount) { if (fromAccount.getBalance().compareTo(amount) < 0) { throw new InsufficientResourcesException(); } else { fromAccount.debit(anount); toAccount.credit(anount); } } } }
A: transferMoney(myAccount, yourAccount, 10);
B: transferMoney(yourAccount, myAccount, 20);
B: transferMoney(yourAccount, myAccount, 20);
由外部传入的变量全部锁的条件,可是由以上传入的变量能够看到,这样的情况下会出现一个线程先获取myAccount锁在申请yourAccount锁,而另外一个线程相反先获取yourAccount锁在申请myAccount锁。
private static final Object tieLock = new Object(); public void transferMoney(final Account fromAccount, final Account toAccount, final DollarAmount anount) throws InsufficientResourcesException { class Helper{ public void transfer() throws InsufficientResourcesException { if (fromAccount.getBalance().compareTo(amount) < 0){ throw new InsufficientResourcesException(); } else{ fromAccount.debit(anount); toAccount.credit(anount); } } } int fromHash = System.identityHashCode(fromAccount); int toHash = System.identityHashCode(toAccount); if (fromHash < toHash){ synchronized (fromAccount){ synchronized (toAccount) { new Helper().transfer(); } } } else if (fromHash > toHash){ synchronized (toAccount){ synchronized (fromAccount) { new Helper().transfer(); } } } else { synchronized (tieLock) { synchronized (fromAccount) { synchronized (toAccount) { new Helper().transfer(); } } } } }
3. 在协作对象之间发生的死锁
class Taxi { 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.notifyAvaliable(this); } } } class Dispatcher { private final Set<Taxi> taxis; private final Set<Taxi> avaliableTaxis; public Dispatcher(){ taxis = new HashSet<Taxi>(); avaliableTaxis = new HashSet<Taxi>(); } public synchronized void notifyAvaliable(Taxi taxi) { avaliableTaxis.add(taxi); } public synchronized Image getImage(){ Image image = new Image(); for (Taxi t :taxis){ image.drawMarker(t.getLocation()); } return image; } }
4. 开放调用
-- 待填充
5. 资源死锁
外部锁常被忽视而导致死锁,比如数据库的锁
二、死锁的避免与诊断
1. 支持定时的死锁
存在一些预防死锁的手段。比方Lock的tryLock,JDK 7中引入的Phaser等。
2. 通过线程转储信息来分析死锁
通过Dump线程的StackTrace,比如linux下运行命令 kill -3 <pid>,或者jstack –l <pid>,或者使用Jconsole连接上去查看线程的StackTrace,由此来诊断死锁问题。
三、其它活跃性危急
1. 饥饿
2. 糟糕的响应性
3. 活锁
四、锁的使用
使用支持CAS的数据结构。避免使用锁。如:AtomicXXX、ConcurrentMap、CopyOnWriteList、ConcurrentLinkedQueue
死锁常常是无法全然避免的,鸵鸟策略被非常多基础框架所採用。
存在检測死锁的办法
五、參考资料:
《温绍锦 - Java并发程序设计教程》
相关文章
- java反转数组_Java实现数组反转翻转的方法实例
- java环境_Java 开发环境配置
- java与python-如何对比Python和Java,只需三分钟告诉你!
- java public interface_Java 接口interface的基础[通俗易懂]
- Java版五子棋小游戏(java控制台)
- java运行环境配置(jdk配置)Java博客 2 年前 桃李Taoli
- 【java并发编程】底层原理——用户态和内核态的区别
- Java并发队列原理剖析
- Deep Java Library_java atomicinteger
- Java并发编程之原子更新类AtomicIntegerFieldUpdater的实例
- java字符串转换为json对象6_Json对象与Json字符串的转化、JSON字符串与Java对象的转换…
- Java并发编程(六)
- 【Java 并发编程】线程池机制 ( ThreadPoolExecutor 线程池构造参数分析 | 核心线程数 | 最大线程数 | 非核心线程存活时间 | 任务阻塞队列 )
- 从java到JavaScript(1),看Dart:对比Java/Go/Swift/Rust
- 关于Java并发编程的总结和思考详解编程语言
- Java并发编程之volatile详解编程语言
- Java并发编程之CyclicBarrier详解编程语言
- Java并发编程之volatile关键字解析详解编程语言
- Java并发编程:线程池的使用详解编程语言
- MySQL与Java互调:构建高效业务系统(mysql调用java)
- Linux与Java结合:开启全新的编程之旅(linux java())
- Java编程与Oracle技术创造技术价值的奥秘(java编程oracle)
- Java与Oracle联手赋能全新版本面世(java版本oracle)
- 并发Redis锁保障Java并发性(redis锁实现java)
- Java并发编程示例(七):守护线程的创建和运行