1、死锁
有这样的情况:一个线程需要同时获取多把锁,这是就容易发生死锁
t1线程获取了A对象锁,接下来想要获取B对象的锁
t2线程获取了B对象锁,接下来想要获取A对象的锁
package com.sharing_model.more_lock;
import javax.crypto.spec.IvParameterSpec;
/**
* 死锁:
* t1线程获取了A对象锁,接下来想要获取B对象的锁
* t2线程获取了B对象锁,接下来想要获取A对象的锁
*/
public class DeadLock {
public static void main(String[] args) {
Object A = new Object();
Object B = new Object();
Thread t1 = new Thread(() -> {
synchronized (A) {
System.out.println("lock A");
try {
Thread.sleep(1000);
synchronized (B) {
System.out.println("lock B");
System.out.println("操作。。。");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread t2 = new Thread(() -> {
synchronized (B) {
try {
System.out.println("lock B");
Thread.sleep(500);
synchronized (A) {
System.out.println("lock A");
System.out.println("操作");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t1.start();
t2.start();
}
}
2、死锁检测
-
jps + jstack
-
jconsole
3、哲学家就餐问题
package com.sharing_model.more_lock;
/**
* 哲学家就餐问题
*/
public class PhilosopherEatFood {
public static void main(String[] args) {
Chopstick c1 = new Chopstick("1");
Chopstick c2 = new Chopstick("2");
Chopstick c3 = new Chopstick("3");
Chopstick c4 = new Chopstick("4");
Chopstick c5 = new Chopstick("5");
new Philosopher("苏格拉底", c1, c2).start();
new Philosopher("柏拉图", c2, c3).start();
new Philosopher("亚里士多德", c3, c4).start();
new Philosopher("赫拉克利特", c4, c5).start();
new Philosopher("阿基米德", c5, c1).start();
}
}
class Philosopher extends Thread {
String name;
Chopstick left;
Chopstick right;
public Philosopher(String name, Chopstick left, Chopstick right) {
this.name = name;
this.left = left;
this.right = right;
}
@Override
public void run() {
while (true) {
//尝试获得左手筷子
synchronized (left) {
//尝试获得右手筷子
synchronized (right) {
eat();
}
}
}
}
private void eat() {
System.out.println(name + "eating...");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class Chopstick {
public Chopstick(String s) {
}
}
执行不一会,就执行不下去了
通过jconsole可以发现
4、活锁
活锁出现在两个线程相互改变对方的结束条件,最后谁也无法结束,例如
/**
* 活锁
*/
public class LiveLock {
static volatile int count = 10;
static final Object Lock = new Object();
public static void main(String[] args) {
new Thread(() -> {
//期望减到0退出
while (count > 0) {
try {
Thread.sleep(200);
count--;
System.out.println("t1:" + count);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "t1").start();
new Thread(() -> {
//期望超过20退出循环
while (count < 20) {
try {
Thread.sleep(200);
count++;
System.out.println("t2:" + count);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
}
5、饥饿
很多教程把饥饿定义为,一个线程由于优先级太低,始终得不到CPU调度执行,也不进行结束