三默网为您带来有关“死锁原因和解决,预防(简单的demo,简单明了说明死锁,理解死锁);多线程交替执行任务(synchronized+ wait+notify 实现)”的文章内容,供您阅读参考。
死锁原因和解决,预防(简单的demo,简单明了说明死锁,理解死锁);多线程交替执行任务(synchronized+ wait+notify 实现)
2023-01-21 13:48:57
死锁:两个或两个以上的线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法执行下去。
下面通过一个简单的demo ,说明死锁的形成。
package com.stcn.news.util;
public class ThreadDemo {
public static void main(String[] args) {
Object lock1=new Object();
Object lock2=new Object();
Thread t1=new Thread(new myThead(lock1,lock2),"t1");
Thread t2=new Thread(new myThead(lock2,lock1),"t2");
t1.start();
t2.start();
}
public static class myThead implements Runnable {
private Object locker1;
private Object locker2;
public myThead(Object locker1, Object locker2) {
this.locker1 = locker1;
this.locker2 = locker2;
}
@Override
public void run() {
synchronized(locker1) { // @1
System.out.println(Thread.currentThread().getName()+ " 获取锁:"+locker1); // @2
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized(locker2) { // @3
System.out.println(Thread.currentThread().getName()+ " 获取锁:"+locker2); // @4
/**
* 这里永远执行不到;
* 代码 @1,@2行 : t1 先进来,获取到了 locker1对象 ; 而t2 进来获取了 locker2对象
* 代码 @3,@4行 : t1 想获取 locker2对象 执行 @4行代码,发现 t2 正在占用 locker2对象 ,t1 此时无法执行下去;
* 而t2 想获取 locker1 对象,执行@4行代码,发现t1 正在占用 locker1 对象,t2 此时无法执行下去;
* 所以造成这个这种僵持的状态:死锁
*/
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
System.out.println("锁被释放了,我被执行了。。。。。。。。。。。。");
}
}
}
死锁的产生的必要条件:
-
互斥条件:一个线程访问资源时候,其他线程不可访问。
-
请求与保持条件: 一个线程请求资源未获取,则持续请求。
-
不可剥夺条件: 一个线程保持这个资源,那么在它释放资源之前,其他线程无法抢夺。
-
彼此循坏等待:多个线程彼此等待一个资源的释放
死锁解决和预防:
-
加锁的顺序:各个线程按照一定顺序加锁。
-
锁的时限设置:万一出现死锁,可保证一定时间内资源得到释放。
-
加锁前的检验:主要预防死锁的产生。
多线程交替执行任务(synchronized+ wait+notify 实现):
package com.stcn.news.util;
/**
* 多个线程交替执行任务 synchronized+ wait+notify 实现
* @author 86136
*/
public class ThreadChangeExcut {
/**
* volatile 保证变量可见性
*/
public static volatile int count = 10;
/**
* 线程申请的同一把锁
*/
public static Object lock=new Object();
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
synchronized(lock) {
while (count>0) {
if(count % 2 == 0){
try {
lock.wait(); // 释放锁进入等待队列(等待池),线程2获取到对象锁
} catch (InterruptedException e) {
e.printStackTrace();
}
}
count--;
if(count >= 0){
System.out.println("当前线程:"+Thread.currentThread().getName()+ "---->B");
}
lock.notify(); // 唤醒等待队列中线程2进入锁池竞争对象锁
}
}
}
},"t1").start();
new Thread(new Runnable() {
@Override
public void run() {
synchronized(lock) {
while (count > 0) {
if (count % 2 != 0) {
try {
lock.wait(); // 释放锁进入等待队列(等待池),线程1获取到对象锁
} catch (InterruptedException e) {
e.printStackTrace();
}
}
count--;
if (count >= 0) {
System.out.println("当前线程:"+Thread.currentThread().getName()+ "---->A");
}
lock.notify(); // 唤醒等待队列中线程1进入锁池竞争对象锁
}
}
}
},"t2").start();
}
}