可重入和不可重入的概念是这样的:当一个线程获得了当前实例的锁,并进入方法A,这个线程在没有释放这把锁的时候,能否再次进入方法A呢?

  • 可重入锁:可以再次进入方法A,就是说在释放锁前此线程可以再次进入方法A(方法A递归)。
  • 不可重入锁(自旋锁):不可以再次进入方法A,也就是说获得锁进入方法A是此线程在释放锁钱唯一的一次进入方法A。

,具体区别查看可重入锁和不可重入锁区别

ReentrantLock,意思是“可重入锁”。ReentrantLock是唯一实现了Lock接口的类,并且ReentrantLock提供了更多的方法。下面通过一些实例看具体看一下如何使用ReentrantLock。

lock()的正确使用方法

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; public class MainLock {
private Lock lock = new ReentrantLock();
public static void main(String[] args) {
final MainLock mainLock = new MainLock(); new Thread(new Runnable() {
@Override
public void run() {
mainLock.insert(Thread.currentThread());
}
}).start(); new Thread(new Runnable() {
@Override
public void run() {
mainLock.insert(Thread.currentThread());
}
}).start();
} public void insert(Thread thread){
lock.lock();//获取锁
try{
System.out.println(thread.getName() + "获取锁");
for(int i=0;i<5;i++){
System.out.println("------------------------" + thread.getName() + ":"+i+"------------------------");
}
}finally {
System.out.println(thread.getName() + "释放锁");
lock.unlock();//释放锁
}
}
}

结果:

Thread-0获取锁
------------------------Thread-0:0------------------------
------------------------Thread-0:1------------------------
------------------------Thread-0:2------------------------
------------------------Thread-0:3------------------------
------------------------Thread-0:4------------------------
Thread-0释放锁
Thread-1获取锁
------------------------Thread-1:0------------------------
------------------------Thread-1:1------------------------
------------------------Thread-1:2------------------------
------------------------Thread-1:3------------------------
------------------------Thread-1:4------------------------
Thread-1释放锁

tryLock()的使用方法

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; public class MainTryLock {
private Lock lock = new ReentrantLock();
public static void main(String[] args) {
final MainTryLock mainTryLock = new MainTryLock(); new Thread(){
@Override
public void run() {
mainTryLock.insert(Thread.currentThread());
}
}.start(); new Thread(){
@Override
public void run() {
mainTryLock.insert(Thread.currentThread());
}
}.start();
} public void insert(Thread thread){
if(lock.tryLock()){
try{
System.out.println(thread.getName() + "获取锁");
for(int i=0;i<5;i++){
Thread.sleep(200);
}
}catch (Exception e){
e.printStackTrace();
}finally {
System.out.println(thread.getName() + "释放锁");
lock.unlock();//释放锁
}
}else{
System.out.println(thread.getName()+"未获取到锁");
}
}
}

结果:

Thread-0获取锁
Thread-1未获取到锁
Thread-0释放锁

lockInterruptibly()响应中断的使用方法:

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; public class MainLockInterruptibl {
private Lock lock = new ReentrantLock();
public static void main(String[] args) {
MainLockInterruptibl test = new MainLockInterruptibl();
MyThread thread1 = new MyThread(test);
MyThread thread2 = new MyThread(test);
thread1.start();
thread2.start(); try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
thread2.interrupt();
} public void insert(Thread thread) throws InterruptedException{
lock.lockInterruptibly(); //注意,如果需要正确中断等待锁的线程,必须将获取锁放在外面,然后将InterruptedException抛出
try {
System.out.println(thread.getName()+"得到了锁");
long startTime = System.currentTimeMillis();
for( int i=0;i<5;i++) {
TimeUnit.SECONDS.sleep(2);
}
} catch (Exception e){
e.printStackTrace();
}finally {
System.out.println(Thread.currentThread().getName()+"执行finally");
lock.unlock();
System.out.println(thread.getName()+"释放了锁");
}
}
static class MyThread extends Thread {
private MainLockInterruptibl test = null;
public MyThread(MainLockInterruptibl test) {
this.test = test;
}
@Override
public void run() {
try {
test.insert(Thread.currentThread());
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println(Thread.currentThread().getName()+"被中断");
}
}
}
}

结果:

Thread-0得到了锁
java.lang.InterruptedException
Thread-1被中断
at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireInterruptibly(AbstractQueuedSynchronizer.java:898)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(AbstractQueuedSynchronizer.java:1222)
at java.util.concurrent.locks.ReentrantLock.lockInterruptibly(ReentrantLock.java:335)
at com.concurrent.MainLockInterruptibl.insert(MainLockInterruptibl.java:25)
at com.concurrent.MainLockInterruptibl$MyThread.run(MainLockInterruptibl.java:48)
Thread-0执行finally
Thread-0释放了锁

源码地址:https://github.com/qjm201000/concurrent_reentrantLock.git

05-11 19:56