重进入是指任意线程在获取锁以后,能够再次获取该锁而不会被锁所阻塞
大白话就是说一个加锁的方法里面调用同一对象中另外一个加锁的方法可以直接获取锁,不会阻塞
阅读完后可以大概了解一下ReentrantLock是个什么东东,然后最好自己去撸下源码,看下原理。
构造
//创建一个非公平获取锁的ReentrantLock实例
ReentrantLock()
//使用给定的公平性策略创建ReentrantLock实例
//true : 公平获取锁
//false: 非公平获取锁 (默认)
ReentrantLock(boolean fair)
ReentrantLock 方法
类型 | 方法 | 描述 |
---|---|---|
int | getHoldCount() | 当前线程对此锁的持有数,如果当前线程不持有此锁,则为零 |
protected Thread | getOwner() | 返回当前拥有此锁的线程,如果不拥有该锁,则返回null |
protected Collection<Thread> | getQueuedThreads() | 返回一个包含可能正在等待获取此锁的线程的集合 |
int | getQueueLength() | 返回等待获取此锁的线程数 |
protected Collection<Thread> | getWaitingThreads(Condition condition) | 返回一个集合,该集合包含那些可能正在等待与此锁关联的给定条件的线程 |
int | getWaitQueueLength(Condition condition) | 返回等待与此锁关联的给定条件的线程数 |
boolean | hasQueuedThread(Thread thread) | 查询给定线程是否正在等待获取此锁 |
boolean | hasQueuedThreads() | 查询是否有任何线程正在等待获取此锁 |
boolean | hasWaiters(Condition condition) | 查询是否有线程正在等待与此锁关联的给定条件 |
boolean | isFair() | 获取公平性策略,公平锁返回ture,反之返回false |
boolean | isHeldByCurrentThread() | 查询此锁是否由当前线程持有 |
boolean | isLocked() | 查询是否有线程持有锁 |
void | lockInterruptibly() | 获取锁,除非当前线程被中断 |
Condition | newCondition() | 返回用于此锁实例的条件实例 |
String | toString() | 返回标识此锁的字符串及其锁定状态 |
boolean | tryLock() | 仅在调用时其他线程未持有该锁时才获取该锁 |
boolean | tryLock(long timeout, TimeUnit unit) | 如果在给定的等待时间内没有被另一个线程持有,并且当前线程没有被中断,则获取该锁 |
void | unlock() | 释放锁 |
例子
package com.sy.thread.example;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.locks.ReentrantLock;
/**
* Description: thread
*
* @author songyu
*/
public class ReentrantLockTest {
static DateTimeFormatter fmTime = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
static ReentrantLock lock = new ReentrantLock();
public static void test(int i) {
//获取锁
lock.lock();
try {
LocalDateTime now = LocalDateTime.now();
System.out.println( now.format(fmTime) + " 第" + i + "个线程获取到锁,等待5秒,释放锁");
Thread.sleep(5000);
} catch (Exception e) {
e.printStackTrace();
} finally {
//释放锁
lock.unlock();
}
}
public static void main(String[] args) {
//连续调用五次test()方法
for (int i = 1; i <= 5; i++ ) {
test(i);
}
}
}
执行结果
2020-07-10 17:24:50 第1个线程获取到锁,等待5秒,释放锁
2020-07-10 17:24:55 第2个线程获取到锁,等待5秒,释放锁
2020-07-10 17:25:00 第3个线程获取到锁,等待5秒,释放锁
2020-07-10 17:25:05 第4个线程获取到锁,等待5秒,释放锁
2020-07-10 17:25:10 第5个线程获取到锁,等待5秒,释放锁
例子 - 重进入
package com.sy.thread.example;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.locks.ReentrantLock;
/**
* Description: thread
*
* @author songyu
*/
public class ReentrantLockTest1 {
static DateTimeFormatter fmTime = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
static ReentrantLock lock = new ReentrantLock(){};
public static void test(int i) {
System.out.println("");
lock.lock();
try {
LocalDateTime now = LocalDateTime.now();
System.out.println( now.format(fmTime) + " 第" + i + "次调用进入方法,等待5秒,释放锁");
//调用另一个需要获取锁的方法
test2(i);
Thread.sleep(5000);
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public static void test2(int i) {
lock.lock();
try {
LocalDateTime now2 = LocalDateTime.now();
//获取当前线程对锁的持有数
int holdCount = lock.getHoldCount();
System.out.println( now2.format(fmTime) + " 第" + i + "次调用 - - 调用第二个需要获取锁的方法 成功再次获取锁,未阻塞");
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
test(i);
}
}
}
执行结果
2020-07-10 18:14:04 第0次调用进入方法,等待5秒,释放锁
2020-07-10 18:14:04 第0次调用 - - 调用第二个需要获取锁的方法 成功再次获取锁,未阻塞
2020-07-10 18:14:09 第1次调用进入方法,等待5秒,释放锁
2020-07-10 18:14:09 第1次调用 - - 调用第二个需要获取锁的方法 成功再次获取锁,未阻塞
2020-07-10 18:14:14 第2次调用进入方法,等待5秒,释放锁
2020-07-10 18:14:14 第2次调用 - - 调用第二个需要获取锁的方法 成功再次获取锁,未阻塞
2020-07-10 18:14:19 第3次调用进入方法,等待5秒,释放锁
2020-07-10 18:14:19 第3次调用 - - 调用第二个需要获取锁的方法 成功再次获取锁,未阻塞
2020-07-10 18:14:24 第4次调用进入方法,等待5秒,释放锁
2020-07-10 18:14:24 第4次调用 - - 调用第二个需要获取锁的方法 成功再次获取锁,未阻塞
线程重复获取了N次锁,只有当线程释放了N次锁以后,其它的线程才能获取锁。
网友评论