一、产生死锁的原因
由于多个线程共同竞争同一个资源导致的一种僵局,若无外力作用,这些进程都将无法继续相向前推进。
eg:
public class DeadLock {
/* public static void a(){
synchronized (String.class){
System.out.println("String上的锁");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (Integer.class){
System.out.println("Integer上的锁");
}
}
}
public static void b(){
synchronized (Integer.class){
System.out.println("Integer上的锁");
synchronized (String.class){
System.out.println("String上的锁");
}
}
}
public static void main(String[] args) {
a();
b();
}*/
public static void main(String[] args) {
final Object a = new Object();
final Object b = new Object();
Thread threadA = new Thread(new Runnable() {
public void run() {
synchronized (a) {
try {
System.out.println("now i in threadA-locka");
Thread.sleep(1000l);
synchronized (b) {
System.out.println("now i in threadA-lockb");
}
} catch (Exception e) {
// ignore
}
}
}
});
Thread threadB = new Thread(new Runnable() {
public void run() {
synchronized (b) {
try {
System.out.println("now i in threadB-lockb");
Thread.sleep(1000l);
synchronized (a) {
System.out.println("now i in threadB-locka");
}
} catch (Exception e) {
// ignore
}
}
}
});
threadA.start();
threadB.start();
}
}
二、死锁产生的条件
1.互斥条件:进程对所分配的资源进行排他性使用,即在一段时间内,某资源只能被一个进程占用。如果此时还有其他进程请求该资源,则请求进程只能等待,直至占有该资源的进程用毕释放;
2.请求与保持条件:进程已经保持了至少一个资源,但又提出了新的资源请求,而该资源已被其他进程占有,此时请求进程被阻塞,但对自己获得资源保持不放;
3.不可抢占条件:进程以获得的资源在未使用完之前不能被抢占,只能在自己使用完后由自己释放;
4.循环等待条件:发生死锁时,必然存在一个(进程--资源)循环链,即进程集合{p0 ,p1 ,p2 ,…,pn}中的p0等待正在等待一个p1占用的资源,p1正在等待p2占用的资源.....
三、检测死锁的方式
1.Jstack工具:java虚拟机自带的一种堆栈跟踪工具。jstack用于打印出给定的java进程ID或core file或远程调试服务的Java堆栈信息。
2.JConsole工具:JDK自带的监控工具,在JDK/bin目录下可以找到。它用于连接正在运行的本地或者远程的JVM,对运行在Java应用程序的资源消耗和性能进行监控,并画出大量的图表,提供强大的可视化界面。
四、如何预防死锁
1.按确定的顺序访问锁
public class DeadLock {
/* public static void a(){
synchronized (String.class){
System.out.println("String上的锁");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (Integer.class){
System.out.println("Integer上的锁");
}
}
}
public static void b(){
synchronized (Integer.class){
System.out.println("Integer上的锁");
synchronized (String.class){
System.out.println("String上的锁");
}
}
}
public static void main(String[] args) {
a();
b();
}*/
public static void main(String[] args) {
final Object a = new Object();
final Object b = new Object();
Thread threadA = new Thread(new Runnable() {
public void run() {
synchronized (a) {
try {
System.out.println("now i in threadA-locka");
Thread.sleep(1000l);
synchronized (b) {
System.out.println("now i in threadA-lockb");
}
} catch (Exception e) {
// ignore
}
}
}
});
Thread threadB = new Thread(new Runnable() {
public void run() {
synchronized (a) {
try {
System.out.println("now i in threadB-lockb");
Thread.sleep(1000l);
synchronized (b) {
System.out.println("now i in threadB-locka");
}
} catch (Exception e) {
// ignore
}
}
}
});
threadA.start();
threadB.start();
}
}