本实验属于没事找事,专门设置对ReentrantLock的几种操作的场景,然后观测线程dump的结果
实验代码
package cn.infobuy.concurrency;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
public class ReentrantLockPractice{
public static void main(String[] args) throws InterruptedException {
// 实验一 执行忘记解锁的实验
// executeUnLockTask();
// 实验二 执行由于加锁顺序不一致导致死锁的实验
// executeDeadLockTask();
// 实验三 执行定时去抢锁的实验
// executeTimeLockTask();
// 实验四 执行中断锁的实验
// executeInterruptDeadLockTask();
}
//-------------------------------------实验一-------------------------------------
/**
* 执行忘记解锁的实验
* @throws InterruptedException
*/
public static void executeUnLockTask() throws InterruptedException {
PracticeUnLockTask practiceBO = new ReentrantLockPractice.PracticeUnLockTask();
Thread t1 = new Thread(practiceBO);t1.setName("task 1 ");
Thread t2 = new Thread(practiceBO);t2.setName("task 2 ");
t1.start();
t2.start();
t1.join();
t2.join();
//等待t1,t2线程运行结束再执行主线程的查看值
System.out.println(practiceBO.i);
}
/**
* 忘记解锁的实验
* @author Administrator
*
*/
static class PracticeUnLockTask implements Runnable{
private int i=0;
private ReentrantLock lock = new ReentrantLock();
@Override
public void run() {
for(int l1=0;l1<10000;l1++) {
lock.lock();
try{
i++;
}finally {
// lock.unlock();
}
}
}
}
//-------------------------------------实验二-------------------------------------
/**
* 执行由于加锁顺序不一致导致死锁的实验
* @throws InterruptedException
*/
public static void executeDeadLockTask() throws InterruptedException {
PracticeDeadLockTask practiceBO = new ReentrantLockPractice.PracticeDeadLockTask(1);
PracticeDeadLockTask practice2BO = new ReentrantLockPractice.PracticeDeadLockTask(2);
Thread t1 = new Thread(practiceBO);t1.setName("task 1 ");
Thread t2 = new Thread(practice2BO);t2.setName("task 2 ");
t1.start();
t2.start();
System.out.println("main thread end");
}
/**
* 加锁顺序不一致导致死锁的实验
* @author Administrator
*
*/
static class PracticeDeadLockTask implements Runnable{
private static ReentrantLock LOCK1 = new ReentrantLock();
private static ReentrantLock LOCK2 = new ReentrantLock();
private int lockWitchFirst=0;
public PracticeDeadLockTask(int lockWitchFirst) {
this.lockWitchFirst=lockWitchFirst;
}
@Override
public void run() {
try {
if(1==lockWitchFirst) {
LOCK1.lock();
Thread.sleep(1000);
LOCK2.lock();
}else {
LOCK2.lock();
Thread.sleep(1000);
LOCK1.lock();
}
}catch(Exception e) {
}finally {
LOCK1.unlock();
LOCK2.unlock();
}
}
}
//-------------------------------------实验三-------------------------------------
/**
* 执行定时去抢锁的实验
* @throws InterruptedException
*/
public static void executeTimeLockTask() throws InterruptedException {
PracticeTimeLockTask practiceBO = new ReentrantLockPractice.PracticeTimeLockTask();
Thread t1 = new Thread(practiceBO);t1.setName("task 1 ");
Thread t2 = new Thread(practiceBO);t2.setName("task 2 ");
t1.start();
t2.start();
}
/**
* 定时去抢锁来避免死锁的情形
* @author Administrator
*
*/
static class PracticeTimeLockTask implements Runnable{
private ReentrantLock lock = new ReentrantLock();
@Override
public void run() {
try {
if(lock.tryLock(5, TimeUnit.SECONDS)) {
System.out.println("try lock success...");
Thread.sleep(6000);
}else {
System.out.println("try lock failure...");
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
if(lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
}
}
//-------------------------------------实验四-------------------------------------
/**
* 执行中断锁的实验
* @throws InterruptedException
*/
public static void executeInterruptDeadLockTask() throws InterruptedException {
PracticeInterruptDeadLockTask practiceBO = new ReentrantLockPractice.PracticeInterruptDeadLockTask(1);
PracticeInterruptDeadLockTask practice2BO = new ReentrantLockPractice.PracticeInterruptDeadLockTask(2);
Thread t1 = new Thread(practiceBO);t1.setName("task 1 ");
Thread t2 = new Thread(practice2BO);t2.setName("task 2 ");
t1.start();
t2.start();
Thread.sleep(1000);
//中断死锁的线程
DeadLockChecker.check();
System.out.println("main thread end");
}
/**
* 中断死锁的实验
* @author Administrator
*
*/
static class PracticeInterruptDeadLockTask implements Runnable{
private static ReentrantLock LOCK1 = new ReentrantLock();
private static ReentrantLock LOCK2 = new ReentrantLock();
private int lockWitchFirst=0;
public PracticeInterruptDeadLockTask(int lockWitchFirst) {
this.lockWitchFirst=lockWitchFirst;
}
@Override
public void run() {
try {
if(1==lockWitchFirst) {
//只有lockInterruptibly的方式 ,lock可以响应中断
LOCK1.lockInterruptibly();
Thread.sleep(1000);
LOCK2.lockInterruptibly();
System.out.println("firstLock1Thread ended");
}else {
LOCK2.lockInterruptibly();
Thread.sleep(1000);
LOCK1.lockInterruptibly();
System.out.println("firstLock2Thread ended");
}
}catch(InterruptedException e) {
System.out.println(Thread.currentThread().getName()+"is interrupted");
e.printStackTrace();
}finally {
if(LOCK1.isHeldByCurrentThread()) {
LOCK1.unlock();
}
if(LOCK2.isHeldByCurrentThread()) {
LOCK2.unlock();
}
}
}
}
}
实验一 reentrantLock在lock之后没有unlock导致的死锁
由dump的内容可知: task2 线程阻塞在ReentrantLock内部类NonfairSync的方法内【NonfairSync便是ReentrantLock内置的非公平锁的实现】
实验二 由于加锁顺序不一致导致的死锁
实验三和实验四的目的是测试reentrantLock锁的特性
ReentrantLock有三种获取锁的方法
1、reentrantLock.lock() 该方法是不会被中断直至线程获取到锁,这个特性和synchronized一样
2、reentrantLock.lockInterruptibly 该方法可通过interrupt方法来中断
3、reentrantLock.tryLock(5,TimeUnit.SECONDS) 该方法可限时去抢锁,获取到锁犯法返回true,超时获取不到则返回false