死锁的概念
在多线程编程中,要执行synchronized块: 必须首先获得指定对象的锁:
public void add (int m)
{
synchronized (obj){
this.value +=m;
}
}
java的线程锁是可重入的锁
public void add (int m){
synchronized(lock){
this.value+=m;
addAnother(m);
}
}
public void addAnother(int m){
synchronized(lock){
this.another+=m;
}
}
public void add (int m){
synchronized(lock){
this.value+=m;
synchronized(lock){
this.another+=m;
}
}
}
java 的线程可以获取多个不同对象的锁
public void add (int m){
synchronized(lockA){ //获得loackA的锁
this.value+=m;
synchronized(lockB){ //获得loackB的锁
this.another+=m;
}// 释放lockB的锁
} //释放lockA的锁
}
不同线程 获取多个不同 对象的锁可能导致死锁
线程 1
public void add (int m){
synchronized(lockB){ //获得loackB的锁
this.value+=m;
synchronized(lockA){ //获得loackA的锁
this.another+=m;
}// 释放lockB的锁
} //释放lockA的锁
}
线程2
public void add (int m){
synchronized(lockA){ //获得loackA的锁
this.value+=m;
synchronized(lockB){ //获得loackB的锁
this.another+=m;
}// 释放lockB的锁
} //释放lockA的锁
}
死锁形成的条件
1、 两个线程各自持有不同的锁
2、 两个线程各自视图获取对方已持有的锁
3、 双方无限等下去: 导致死锁
死锁发生后:
1、 没有任何机制能接触死锁
2、 只能强制结束JVM进程
如何避免死锁: 线程获取锁的顺序要一致
线程 1
public void add (int m){
synchronized(lockA){ //获得loackA的锁
this.value+=m;
synchronized(lockB){ //获得loackB的锁
this.another+=m;
}// 释放lockB的锁
} //释放lockA的锁
}
线程2
public void add (int m){
synchronized(lockA){ //获得loackA的锁
this.value+=m;
synchronized(lockB){ //获得loackB的锁
this.another+=m;
}// 释放lockB的锁
} //释放lockA的锁
}
死锁的例子
class SharedObject {
final Object lockA = new Object();
final Object lockB = new Object();
int accountA = 1000;
int accountB = 2000;
public void a2b(int balance) {
synchronized (lockA) {
accountA -= balance;
synchronized (lockB) {
accountB += balance;
}
}
}
public void b2a(int balance) {
synchronized (lockB) {
accountB -= balance;
synchronized (lockA) {
accountA += balance;
}
}
}
}
class AThread extends Thread {
public void run() {
for (int i = 0; i < Main.LOOP; i++) {
Main.shared.a2b(1);
if (i % 100 == 0) {
System.out.println(".");
}
}
}
}
class BThread extends Thread {
public void run() {
for (int i = 0; i < Main.LOOP; i++) {
Main.shared.b2a(1);
if (i % 100 == 0) {
System.out.println(".");
}
}
}
}
public class Main {
final static int LOOP = 1000;
public static SharedObject shared = new SharedObject();
public static void main(String[] args) throws Exception {
Thread t1 = new AThread();
Thread t2 = new BThread();
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("END");
}
}
总结:
死锁产生的条件:
如何避免死锁: