死锁
说到死锁,大家可能都不陌生,每次遇到死锁,总会让计算机产生比较严重的后果,比如资源耗尽,界面无响应等。
当线程需要同时持有多个锁时,有可能产生死锁。考虑如下情形:线程 A 当前持有互斥所锁 lock1,线程 B 当前持有互斥锁 lock2。接下来,当线程 A 仍然持有 lock1 时,它试图获取 lock2,因为线程 B 正持有 lock2,因此线程 A 会阻塞等待线程 B 对 lock2 的释放。
死锁是两个或更多线程阻塞着等待其它处于死锁状态的线程所持有的锁。死锁通常发生在多个线程同时但以不同的顺序请求同一组锁的时候。例如,如果线程 1 锁住了 A,然后尝试对 B 进行加锁,同时线程 2 已经锁住了 B,接着尝试对 A 进行加锁,这时死锁就发生了。线程 1 永远得不到 B,线程 2 也永远得不到 A,并且它们永远也不会知道发生了这样的事情。
如果我们在程序中遇到线程死锁的时候,该怎么去解决呢?本文将会从一个实际的例子出发,一步一步的揭开java问题解决的面纱。
死锁(Deadlock)就是一个进程拿着资源A请求资源B,另一个进程拿着资源B请求资源A,双方都不释放自己的资源,导致两个进程都进行不下去。示例程序我们可以写代码模拟进程死锁的例子。package mainfunc main() { ch := make(chan int) <-ch}运行结果root@fa13d0439d7a:/go/src# go run deadlock.gofatal error: all goroutines are asleep - deadlock!
分布式数仓应用场景中,我们经常遇到数据库系统 hang 住的问题,所谓 hang 是指虽然数据库系统还在运行,但部分或全部业务无法正常执行。hang 问题的原因有很多,其中以分布式死锁最为常见,本次主要分享在碰到死锁时,如何快速地解决死锁问题。
在有些情况下死锁是可以避免的。本文将展示三种用于避免死锁的技术:加锁顺序加锁时限死锁检测加锁顺序当多个线程需要相同的一些锁,但是按照不同的顺序加锁,死锁就很容易发生。如果能确保所有的线程都是按照相同的顺序获得锁,那么死锁就不会发生。
上面的例子中,我们模拟一个转账的过程,amount用来表示用户余额。transfer用来将当前账号的一部分金额转移到目标对象中。为了保证在transfer的过程中,两个账户不被别人修改,我们使用了两个synchronized关键字,分别把transfer对象和目标对象进行锁定。
关注时代Java