死锁的概念
“死锁”指的是:
多个线程各自占有一些共享资源,并且互相等待其他线程占有的资源才能进行,而导致两个或者多个线程都在等待对方释放资源,都停止执行的情形。
因此, 某一个同步块需要同时拥有“两个以上对象的锁”时,就可能会发生“死锁”的问题。下面案例中,“化妆线程”需要同时拥有“镜子对象”、“口红对象”才能运行同步块。那么,实际运行时,“小丫的化妆线程”拥有了“镜子对象”,“大丫的化妆线程”拥有了“口红对象”,都在互相等待对方释放资源,才能化妆。这样,两个线程就形成了互相等待,无法继续运行的“死锁状态”。
【示例】死锁问题
public class TestDeadLock {
public static void main(String[] args) {
Girl girl1=new Girl("大丫",0);
Girl girl2=new Girl("小丫",1);
girl1.start();
girl2.start();
}
}
class Mirror{
}
class Lipstick{
}
class Girl extends Thread{
static Mirror mirror=new Mirror();
static Lipstick lipstick=new Lipstick();
String name;
int flag;
public Girl(String name,int flag){
this.name=name;
this.flag=flag;
}
public void run(){
makeup();
}
public void makeup(){
if(this.flag==0){
synchronized (lipstick){
System.out.println(this.name+"拿到了口红");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (mirror){
System.out.println(this.name+"拿到了镜子");
}
}
}else{
synchronized (mirror){
System.out.println(this.name+"拿到了镜子");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lipstick){
System.out.println(this.name+"拿到了口红");
}
}
}
}
}
【运行结果】
死锁的解决方法
死锁是由于“同步块需要同时持有多个对象锁造成”的,要解决这个问题,思路很简单,就是:同一个代码块,不要同时持有两个对象锁。 如上面的死锁案例
【示例】死锁问题的解决
public class TestDeadLock {
public static void main(String[] args) {
Girl girl1=new Girl("大丫",0);
Girl girl2=new Girl("小丫",1);
girl1.start();
girl2.start();
}
}
class Mirror{
}
class Lipstick{
}
class Girl extends Thread{
static Mirror mirror=new Mirror();
static Lipstick lipstick=new Lipstick();
String name;
int flag;
public Girl(String name,int flag){
this.name=name;
this.flag=flag;
}
public void run(){
makeup();
}
public void makeup(){
if(this.flag==0){
synchronized (lipstick){
System.out.println(this.name+"拿到了口红");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
synchronized (mirror){
System.out.println(this.name+"拿到了镜子");
}
}else{
synchronized (mirror){
System.out.println(this.name+"拿到了镜子");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
synchronized (lipstick) {
System.out.println(this.name + "拿到了口红");
}
}
}
}
【运行结果】