死锁的代码示例
//两个线程
public class JiYan extends Thread{
private String lock1 = null ;
private String lock2 = null ;
public JiYan (String lock1,String lock2){
this.lock1 = lock1;
this.lock2 = lock2;
}
@Override
public void run() {
synchronized (lock1){
System.out.println("忌炎正在使用"+ lock1);
synchronized (lock2){
System.out.println("忌炎正在使用" + lock2);
}
System.out.println("忌炎放下了"+lock2);
}
System.out.println("忌炎放下了" + lock1);
}
}
}//忌炎在使用lock2对应的武器时并未释放lock1对应的武器
public class Calcharo extends Thread{
private String lock1;
private String lock2;
public Calcharo(String lock1, String lock2) {
this.lock1 = lock1;
this.lock2 = lock2;
}
@Override
public void run() {
synchronized (lock1){
System.out.println("卡卡罗正在使用" + lock1);
synchronized (lock2){
System.out.println("卡卡罗正在使用" + lock2);
}
System.out.println("卡卡罗放下了"+lock2);
}
System.out.println("卡卡罗放下了" + lock1);
}
}
}
public class Test {
public static void main(String[] args) throws Exception {
String lock1 = "忌炎专武";//字符串可以作为锁但一般不建议这样使用
String lock2 = "普池五星大剑";
Thread jiyan = new JiYan(lock2,lock1);
Thread calcharo = new Calcharo(lock1,lock2);
calcharo.start();
//calcharo.sleep(1);
jiyan.start();
}
}
//运行结果
//未使用sleep()时,两者争夺武器,未能释放资源
忌炎正在使用普池五星大剑
卡卡罗正在使用忌炎专武
//使用sleep()时,卡卡罗先使用武器,并接着能够使用第二把,放下之后,资源全部释放,忌炎能够使用两把武器
卡卡罗正在使用忌炎专武
卡卡罗正在使用普池五星大剑
卡卡罗放下了普池五星大剑
卡卡罗放下了忌炎专武
忌炎正在使用普池五星大剑
忌炎正在使用忌炎专武
忌炎放下了忌炎专武
忌炎放下了普池五星大剑
死锁的四个条件:(个人学习只考虑线程)
互斥性:线程互斥
循环等待:线程等待资源释放
不可剥夺:线程的锁不可被其他线程强制破坏
请求与保持:线程不会放弃自己的锁
1.死锁不可避免只能解决,破坏任一条件即可解决死锁,一般为请求与保持
2.Lock中的ReentrantLock可以解决死锁问题,其主动获取和释放锁
Lock为接口
ReentrantLock为其唯一子类,其他类为内部类
使用:显式定义
Lock lock = new ReentrantLock();
可重入性:嵌套使用同一个锁
ReentranLock和synchronized都具是可重入锁
synchronized:
public class Test {
public static void main(String[] args) {
String lock = "钧天正音";
synchronized(lock){
System.out.println("使用"+lock+"攻击");
{
synchronized(lock){
System.out.println("使用"+lock+"演奏");
System.out.println("演奏中...");
}
System.out.println("停止使用"+lock+"演奏");
}
System.out.println("停止使用"+lock+"攻击");
}
}
}
//运行结果
使用钧天正音攻击
使用钧天正音演奏
演奏中...
停止使用钧天正音演奏
停止使用钧天正音攻击
ReentrantLock:
//子线程
public class Play extends Thread{
private Lock lock;
public Play(Lock lock){
this.lock = lock;
}
@Override
public void run() {
try{
lock.lock();
System.out.println("演奏");
for (int i = 0; i < 5; i++) {
System.out.println("嘟");
Thread.sleep(5000);//间隔5秒
}
} catch (Exception e) {
e.printStackTrace();
}finally {
lock.unlock();
System.out.println("停止演奏");
}
}
}
public class Test {
public static void main(String[] args) throws Exception {
Lock lock = new ReentrantLock();
Thread play = new Play(lock);
play.start();
Thread.sleep(1);//主线程休眠,使子线程先持有锁
try{
lock.lock();
System.out.println("使用武器攻击");
} catch (Exception e) {
e.printStackTrace();
}finally {
lock.unlock();
System.out.println("放下攻击武器");
}
}
}
//运行结果
演奏
嘟
嘟
嘟
嘟
嘟
停止演奏
使用武器攻击
放下攻击武器