1 可中断
public class ReentranLockInterruptibly implements Runnable {
private static ReentrantLock reentrantLock01 = new ReentrantLock();
private static ReentrantLock reentrantLock02 = new ReentrantLock();
private Integer count = 0;
public ReentranLockInterruptibly(Integer count) {
this.count = count;
}
@Override
public void run() {
try {
if (count == 1) {
reentrantLock01.lockInterruptibly();
Thread.sleep(500);
reentrantLock02.lockInterruptibly();
} else {
reentrantLock02.lockInterruptibly();
Thread.sleep(500);
reentrantLock01.lockInterruptibly();
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
if (reentrantLock01.isHeldByCurrentThread()) {
reentrantLock01.unlock();
}
if (reentrantLock02.isHeldByCurrentThread()) {
reentrantLock02.unlock();
}
System.out.println(Thread.currentThread().getId() + ":线程退出");
}
}
public static void main(String[] args) throws InterruptedException {
ReentranLockInterruptibly lockInterruptibly1 = new ReentranLockInterruptibly(
1);
ReentranLockInterruptibly lockInterruptibly2 = new ReentranLockInterruptibly(
2);
Thread thread01 = new Thread(lockInterruptibly1);
Thread thread02 = new Thread(lockInterruptibly2);
thread01.start();
thread02.start();
Thread.sleep(1000);
DeadLockChecker.checkDeadLock();
}
}
死锁的原因:第一个线程获取reentrantLock01锁,线程被挂起,第二个线程开始获得reentrantLock02锁,第二个线程睡眠,轮到第一个线程开始执行。想获取reentrantLock02锁,但是已经被第二个线程获取了,陷入阻塞状态,等待释放锁资源,轮到第二个线程执行,想要获取reentrantLock01锁,但是发现已经被占用了,陷入了阻塞状态。两个线程都在等待对方释放锁资源,陷入死锁。
解决办法:启动一个守护线程,继承当前各个线程间是否陷入的死锁。
守护线程实现:
public class DeadLockChecker {
private final static ThreadMXBean mbean = ManagementFactory
.getThreadMXBean();
final static Runnable deadLockCheck = new Runnable() {
@Override
public void run() {
while (true) {
long[] deadLockedThreadIds = mbean.findDeadlockedThreads();
if (deadLockedThreadIds != null) {
ThreadInfo[] threadInfos = mbean
.getThreadInfo(deadLockedThreadIds);
for (Thread thread : Thread.getAllStackTraces().keySet()) {
for (int i = 0; i < threadInfos.length; i++) {
if (thread.getId() == threadInfos[i].getThreadId()) {
thread.interrupt();
}
}
}
}
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
};
public static void checkDeadLock() {
Thread thread = new Thread(deadLockCheck);
thread.setDaemon(true);
thread.start();
}
}
2 可限时
获取锁资源的限时性,如果一段时间内获取不到锁资源,将会返回
/**
* 限时获取锁资源
*
* @author Tang 2018年6月30日
*/
public class ReentranLockTimeOut implements Runnable {
private static ReentrantLock reentrantLock = new ReentrantLock();
@Override
public void run() {
try {
if (reentrantLock.tryLock(5, TimeUnit.SECONDS)) {
Thread.sleep(6000);
} else {
System.out.println("get lock failed");
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
if(reentrantLock.isHeldByCurrentThread()){
reentrantLock.unlock();
}
}
}
public static void main(String[] args) {
ReentranLockTimeOut reentranLockTime = new ReentranLockTimeOut();
Thread thread01 = new Thread(reentranLockTime);
Thread thread02 = new Thread(reentranLockTime);
thread01.start();
thread02.start();
}
}
3 公平锁
构造方法ReentrantLock中一个参数,设置为true,这创建一个公平锁,保证先来的先得,后来的后得。一般情况下是先来的不一定先得,后来的不一定是后得。解决得到锁的不确定性。但是公平锁的性能可能不是蛮好,因为要处理排队的问题。
如下创建一个公平锁:
private static ReentrantLock reentrantLock=new ReentrantLock(true);
4 Condition
public class ReentranLockCondition implements Runnable {
private static ReentrantLock reentrantLock = new ReentrantLock();
private static Condition condition = reentrantLock.newCondition();
@Override
public void run() {
try {
reentrantLock.lock();
condition.await();
System.out.println("Thread is going on");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
if (reentrantLock.isHeldByCurrentThread()) {
reentrantLock.unlock();
}
}
}
public static void main(String[] args) throws InterruptedException {
ReentranLockCondition reentranLockCondition = new ReentranLockCondition();
Thread thread01 = new Thread(reentranLockCondition);
thread01.start();
Thread.sleep(1000);
// 通知线程继续执行
reentrantLock.lock();
condition.signal();
reentrantLock.unlock();
}
}