JAVA多线程——死锁
死锁问题:多个线程互相拿着对方需要的资源,然后形成僵持
出现死锁后,不会出现异常,不会出现提示,只是所有的线程都处于阻塞状态,无法继续
死锁问题的演示
package com.work;
public class work6 {
public static void main(String[] args) {
StringBuffer s1 = new StringBuffer();
StringBuffer s2 = new StringBuffer();
//线程一
new Thread(){
//用匿名内部类的方式创建线程(继承Thread类)
@Override
public void run() {
synchronized(s1){
//线程一先获得s1的锁
s1.append("a");
s2.append(1);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized(s2){
//再获得s2的锁
s1.append("b");
s2.append(2);
//线程一只有同时获得了s1和s2的锁才能输出s1,s2
System.out.println(s1);
System.out.println(s2);
}
}
}
}.start();
//线程二
new Thread(new Runnable() {
//实现Runnable接口
@Override
public void run() {
synchronized (s2) {
//线程二先获得s2的锁
s1.append("c");
s2.append(3);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (s1) {
//再获得s1的锁
s1.append("d");
s2.append(4);
System.out.println(s1);
System.out.println(s2);
}
}
}
}).start();
}
}
案例二
package com.peng.demon06;
import com.sun.deploy.security.SelectableSecurityManager;
//死锁:多个线程互相拿着对方需要的资源,然后形成僵持
//案例背景:白雪公主,灰胡娘两个人都想化妆,但只有有个镜子和一个口红,然后一个人拿着口红,一个人拿着镜子,导致谁也化不了
public class DeadLock {
public static void main(String[] args) {
Makeup g1 = new Makeup(0,"白雪公主");
Makeup g2 = new Makeup(1,"灰胡娘");
g1.start();
g2.start();
}
}
//口红
class Lipstick{
}
//镜子
class Mirror{
}
//化妆的类
class Makeup extends Thread{
//化妆需要的资源就只有一份,因此用static来保证只有一份
static Lipstick lipstick = new Lipstick();
static Mirror mirror = new Mirror();
int choice;//选择
String girlName;//化妆的人名字
//构造器
public Makeup(int choice,String girlName){
this.choice=choice;
this.girlName=girlName;
}
@Override
public void run() {
try {
makeup();
} catch (InterruptedException e) {
e.printStackTrace();
}
}//化妆的方法
private void makeup() throws InterruptedException {
if (choice==0){
//第一个人
synchronized (lipstick){
//获得口红对象的锁
System.out.println(this.girlName+"获得口红的锁");
Thread.sleep(1000);
//两个同步块在一起
synchronized (mirror){
//一秒后还想获得镜子的锁
System.out.println(this.girlName+"获得镜子的锁");
}
}
}else {
//第二个人
synchronized (mirror){
//获得镜子对象的锁
System.out.println(this.girlName+"获得口红的锁");
Thread.sleep(2000);
synchronized (lipstick){
//2秒后还想获得口红的锁
System.out.println(this.girlName+"获得镜子的锁");
}
}
}
}
}
死锁导致程序卡死
解决方法:把两个同步块分开来放,不要放在一起,不要让两个线程互相抱对方的锁
package com.peng.demon06;
import com.sun.deploy.security.SelectableSecurityManager;
//死锁:多个线程互相拿着对方需要的资源,然后形成僵持
public class DeadLock {
public static void main(String[] args) {
Makeup g1 = new Makeup(0,"白雪公主");
Makeup g2 = new Makeup(1,"灰胡娘");
g1.start();
g2.start();
}
}
//口红
class Lipstick{
}
//镜子
class Mirror{
}
//化妆的类
class Makeup extends Thread{
//化妆需要的资源就只有一份,因此用static来保证只有一份
static Lipstick lipstick = new Lipstick();
static Mirror mirror = new Mirror();
int choice;//选择
String girlName;//化妆的人名字
//构造器
public Makeup(int choice,String girlName){
this.choice=choice;
this.girlName=girlName;
}
@Override
public void run() {
try {
makeup();
} catch (InterruptedException e) {
e.printStackTrace();
}
}//化妆的方法
private void makeup() throws InterruptedException {
if (choice==0){
//第一个人
synchronized (lipstick){
//获得口红对象的锁
System.out.println(this.girlName+"获得口红的锁");
Thread.sleep(1000);
} synchronized (mirror){
//一秒后还想获得镜子的锁
System.out.println(this.girlName+"获得镜子的锁");
}
}else {
//第二个人
synchronized (mirror){
//获得镜子对象的锁
System.out.println(this.girlName+"获得镜子的锁");
Thread.sleep(2000);
} synchronized (lipstick){
//2秒后还想获得口红的锁
System.out.println(this.girlName+"获得口红的锁");
}
}
}
}
产生死锁的四个必要条件
- 互斥条件:一个资源每次只能宝贝一个进程使用
- 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放
- 不剥夺条件:进程已获得的资源,在未使用完之前,不能强行剥夺
- 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系
我们只要想办法破其中一种或多种条件就可以避免死锁的发生