避免死锁
避免死锁
ReentrantLock
使用tryLock() 方法来防止多线程死锁。
该示例启动两个线程。线程
public class DeadLock1 {
private static Lock lock1 = new ReentrantLock();
private static Lock lock2 = new ReentrantLock();
public static void deathLock() {
new Thread() {
@Override
public void run() {
while (true) {
if (lock1.tryLock()) {
try {
// 如果获取成功则执行业务逻辑,如果获取失败,则释放lock1的锁,自旋重新尝试获得锁
if (lock2.tryLock()) {
try {
System.out.println("Thread1:已成功获取 lock1 and lock2 ...");
break;
} finally {
lock2.unlock();
}
}
} finally {
lock1.unlock();
}
}
System.out.println("Thread1:获取锁失败,重新获取---");
try {
//防止发生活锁
TimeUnit.NANOSECONDS.sleep(new Random().nextInt(100));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
new Thread() {
@Override
public void run() {
while (true) {
if (lock2.tryLock()) {
try {
//如果获取成功则执行业务逻辑,如果获取失败,则释放lock2的锁,自旋重新尝试获得锁
if (lock1.tryLock()) {
try {
System.out.println("Thread2:已成功获取 lock2 and lock1 ...");
break;
} finally {
lock1.unlock();
}
}
} finally {
lock2.unlock();
}
}
System.out.println("Thread2:获取锁失败,重新获取---");
try {
//防止发生活锁
TimeUnit.NANOSECONDS.sleep(new Random().nextInt(100));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 5; i++) {
deathLock();
}
}
}
我们这里使用
使用tryLock(long timeout, TimeUnit unit) 方法来防止多线程死锁。
import java.util.Random;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class DeadLock2 {
private static ReentrantLock lock1 = new ReentrantLock();
private static ReentrantLock lock2 = new ReentrantLock();
public static void deathLock() {
new Thread() {
@Override
public void run() {
while (true) {
try {
if (lock1.tryLock(10, TimeUnit.MILLISECONDS)) {
try {
//如果获取成功则执行业务逻辑,如果获取失败,则释放lock1的锁,自旋重新尝试获得锁
if (lock2.tryLock(10, TimeUnit.MILLISECONDS)) {
System.out.println("Thread1:已成功获取 lock1 and lock2 ...");
break;
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
if(lock2.isHeldByCurrentThread()){
lock2.unlock();
}
}
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
if(lock1.isHeldByCurrentThread()){
lock1.unlock();
}
}
System.out.println("Thread1:获取锁失败,重新获取---");
try {
TimeUnit.NANOSECONDS.sleep(new Random().nextInt(100));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
new Thread() {
@Override
public void run() {
while (true) {
try {
if (lock2.tryLock(10, TimeUnit.MILLISECONDS)) {
try {
//如果获取成功则执行业务逻辑,如果获取失败,则释放lock1的锁,自旋重新尝试获得锁
if (lock1.tryLock(10, TimeUnit.MILLISECONDS)) {
System.out.println("Thread2:已成功获取 lock2 and lock1 ...");
break;
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
if(lock1.isHeldByCurrentThread()){
lock1.unlock();
}
}
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
if(lock2.isHeldByCurrentThread()){
lock2.unlock();
}
}
System.out.println("Thread2:获取锁失败,重新获取---");
try {
TimeUnit.NANOSECONDS.sleep(new Random().nextInt(100));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 5; i++) {
deathLock();
}
}
}
lockInterruptibly()
使用
public class DeadLock3 {
private static Lock lock1 = new ReentrantLock();
private static Lock lock2 = new ReentrantLock();
public static void deathLock() {
new Thread() {
@Override
public void run() {
try {
lock1.lockInterruptibly();
try {
TimeUnit.SECONDS.sleep(1);
lock2.lockInterruptibly();
System.out.println("thread 1 ...");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock2.unlock();
}
} catch (InterruptedException e1) {
e1.printStackTrace();
} finally {
lock1.unlock();
}
}
}.start();
new Thread() {
@Override
public void run() {
try {
lock2.lockInterruptibly();
try {
TimeUnit.SECONDS.sleep(1);
lock1.lockInterruptibly();
System.out.println("thread 1 ...");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock1.unlock();
}
} catch (InterruptedException e1) {
e1.printStackTrace();
} finally {
lock2.unlock();
}
}
}.start();
}
public static void main(String[] args) throws InterruptedException {
deathLock();
TimeUnit.SECONDS.sleep(2);
checkDeadLock();
}
//基于JMX获取线程信息
public static void checkDeadLock() {
//获取Thread的MBean
ThreadMXBean mbean = ManagementFactory.getThreadMXBean();
//查找发生死锁的线程,返回线程id的数组
long[] deadLockThreadIds = mbean.findDeadlockedThreads();
System.out.println("---" + deadLockThreadIds);
if (deadLockThreadIds != null) {
//获取发生死锁的线程信息
ThreadInfo[] threadInfos = mbean.getThreadInfo(deadLockThreadIds);
//获取JVM中所有的线程信息
Map<Thread, StackTraceElement[]> map = Thread.getAllStackTraces();
for (Entry<Thread, StackTraceElement[]> entry : map.entrySet()) {
for (int i = 0; i < threadInfos.length; i++) {
Thread t = entry.getKey();
if (t.getId() == threadInfos[i].getThreadId()) {
//中断发生死锁的线程
t.interrupt();
//打印堆栈信息
// for (StackTraceElement ste : entry.getValue()) {
// // System.err.println("t" + ste.toString().trim());
// }
}
}
}
}
}
}
我们这里使用