Java中死锁的例子及其解决办法
程序员文章站
2022-05-04 18:17:37
...
Java中死锁的例子及其解决办法
什么是死锁?
过多的同步可能会造成死锁。(相互等资源)
某一个同步块同时拥有两个或者两个以上的对象的锁时,可能发生死锁。
比如下面这个例子:
线程1已经持有了lipstick锁并想要获得mirror锁的同时,线程2持有mirror锁并尝试获取lipstick锁,那么这两个线程将永远地等待下去。
看代码例子:
/**
* 死锁:过多的同步可能造成相互不释放资源
* 从而相互等待,一般发生于同步中持有多个对象的锁
* 解决方法:不要在同一个代码块中,出现多个对象的锁(锁套锁)
* @author Administrator
*
*/
public class DeadLock {
public static void main(String[] args) {
Makeup g1=new Makeup(0, "girl a");
Makeup g2=new Makeup(1, "girl b");
g1.start();
g2.start();
}
}
//口红
class Lipstick{
}
//镜子
class Mirror{
}
//化妆
class Makeup extends Thread{
static Lipstick lipstick=new Lipstick();
static Mirror mirror=new Mirror();
int choice;//选择
String girl;//名字
public Makeup(int choice,String girl) {
this.choice = choice;
this.girl = girl;
}
@Override
public void run() {
makeup();
}
//相互持有对方的对象锁-->可能造成死锁
private void makeup() {
if(choice==0) {
synchronized(lipstick) {//获得口红的锁
System.out.println(this.girl+"获得口红");
//1秒后,1秒内girl b完全可以拿到mirror
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized(mirror) {
System.out.println(this.girl+"获得镜子");
}
}
}
else {
synchronized(mirror) {//获得镜子的锁
System.out.println(this.girl+"获得镜子");
//2秒后,2秒内girl a完全可以拿到lipstick
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized(lipstick) {
System.out.println(this.girl+"获得口红");
}
}
}
}
}
运行结果(可以看出发生了死锁):
可知:线程1先拿到了口红,在拿到口红的基础上,想拿镜子,而线程2先拿到了镜子,在拿到镜子基础上,想拿口红,那么结果就是,两个线程会无休止的等待下去。
解决办法:
不要在同一个代码块中,出现多个对象的锁(锁套锁);
例如红色标记不要嵌套在紫色标记里:
解决后的代码为:
/**
* 死锁:过多的同步可能造成相互不释放资源
* 从而相互等待,一般发生于同步中持有多个对象的锁
* 解决方法:不要在同一个代码块中,出现多个对象的锁(锁套锁)
* @author Administrator
*
*/
public class DeadLock {
public static void main(String[] args) {
Makeup g1=new Makeup(0, "girl a");
Makeup g2=new Makeup(1, "girl b");
g1.start();
g2.start();
}
}
//口红
class Lipstick{
}
//镜子
class Mirror{
}
//化妆
class Makeup extends Thread{
static Lipstick lipstick=new Lipstick();
static Mirror mirror=new Mirror();
int choice;//选择
String girl;//名字
public Makeup(int choice,String girl) {
this.choice = choice;
this.girl = girl;
}
@Override
public void run() {
makeup();
}
//相互持有对方的对象锁-->可能造成死锁
private void makeup() {
if(choice==0) {
synchronized(lipstick) {//获得口红的锁
System.out.println(this.girl+"获得口红");
//1秒后,1秒内girl b完全可以拿到mirror
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
synchronized(mirror) {
System.out.println(this.girl+"获得镜子");
}
}
else {
synchronized(mirror) {//获得镜子的锁
System.out.println(this.girl+"获得镜子");
//2秒后,2秒内girl a完全可以拿到lipstick
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
synchronized(lipstick) {
System.out.println(this.girl+"获得口红");
}
}
}
}
运行结果:
那么要怎么预防死锁呢?下面介绍几个常见方法:
1、避免一个线程同时获取多个锁
2、避免一个线程在锁内同时占用多个资源,尽量保证每个锁只占用一个资源
3、尝试使用定时锁,使用lock.tryLock来代替使用内置锁。
上一篇: Quick_Python_0
下一篇: JAVA简易WEB服务器(三)