ReentrantLock是一个可重入的独占锁,同一线程可重复获取锁的状态,该锁一次只能被一个线程所持有。
ReentrantLock() :创建 ReentrantLock实例,随机分配使用权。
ReentrantLock(boolean fair) :创建具有公平政策的ReentrantLock实例,在锁上等待时间最长的线程将获取锁的使用权(先来先得)。
int getHoldCount()
查询当前线程持有这个锁的数量,每 lock.lock();一次该数量+1。
protected Thread getOwner()
返回拥有该锁的线程,如果没有返回null,该方法是一个受保护的方法,需要使用一个类来extends ReentrantLock类,在继承类中操作。
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()
是公平锁返回true。
boolean isHeldByCurrentThread()
查询当前线程是否持有此锁。
boolean isLocked()
查询此锁是否由线程持有。
void lock()
获取锁。
void lockInterruptibly()
获取该锁除非当前线程是被interrupt()方法中断的。
Condition newCondition()
返回一个用于这 Lock实例 Condition实例。
String toString()
返回一个确定此锁的字符串,以及它的锁状态。
boolean tryLock()
尝试获取锁,只有在调用时锁没有被另一个线程持有时才获取锁。。
boolean tryLock(long timeout, TimeUnit unit)
如果在给定的等待时间内没有被其他线程持有,并且当前线程没有被interrupt()中断,则获取锁
void unlock()
试图释放这个锁。
static AtomicInteger num = new AtomicInteger(0);
//初始化可重入锁
static Lock lock = new ReentrantLock();
static Condition addCondition = lock.newCondition();
static Condition subCondition = lock.newCondition();
static int j = 0;
public static void main(String[] args) throws InterruptedException {
//初始化A线程
Thread threadAdd = new Thread(new Runnable() {
@Override
public void run() {
//需要先获得锁
lock.lock();
System.out.println("threadAdd:获得锁");
try {
System.out.println("threadAdd:开始加");
//A线程先输出前3个数
while (true) {
Thread.sleep(1000);
while (num.intValue() < 10) {
num.incrementAndGet();
}
System.out.println("threadAdd:已经加到10了,告诉threadSub开始,等待threadSub通知我再继续执行");
//输出到10时要signal,告诉threadSub线程可以开始了
subCondition.signal();
addCondition.await();
j++;
//跳出循环,并且通知subCondition继续
if(j>5) {
System.out.println("threadAdd:循环了5次了,不继续了,跳出循环让threadSub再继续执行");
subCondition.signal();
break;
}
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
System.out.println("threadAdd:释放lock");
}
}
});
Thread threadSub = new Thread(new Runnable() {
@Override
public void run() {
try {
lock.lock();
System.out.println("threadSub:获得锁");
while (true) {
Thread.sleep(1000);
while (num.intValue() > 0) {
num.decrementAndGet();
}
System.out.println("threadSub:已经减到0了,告诉threadAdd开始,等待threadAdd通知我再继续执行");
addCondition.signal();
subCondition.await();
if(j>5) {
System.out.println("threadSub:循环了5次了,我也不继续了,跳出循环");
break;
}
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
System.out.println("threadSub:释放lock");
}
}
});
//启动两个线程
threadAdd.start();
Thread.sleep(1);
threadSub.start();
}
结果
threadAdd:获得锁
threadAdd:开始加
threadAdd:已经加到10了,告诉threadSub开始,等待threadSub通知我再继续执行
threadSub:获得锁
threadSub:已经减到0了,告诉threadAdd开始,等待threadAdd通知我再继续执行
threadAdd:已经加到10了,告诉threadSub开始,等待threadSub通知我再继续执行
threadSub:已经减到0了,告诉threadAdd开始,等待threadAdd通知我再继续执行
threadAdd:已经加到10了,告诉threadSub开始,等待threadSub通知我再继续执行
threadSub:已经减到0了,告诉threadAdd开始,等待threadAdd通知我再继续执行
threadAdd:已经加到10了,告诉threadSub开始,等待threadSub通知我再继续执行
threadSub:已经减到0了,告诉threadAdd开始,等待threadAdd通知我再继续执行
threadAdd:已经加到10了,告诉threadSub开始,等待threadSub通知我再继续执行
threadSub:已经减到0了,告诉threadAdd开始,等待threadAdd通知我再继续执行
threadAdd:已经加到10了,告诉threadSub开始,等待threadSub通知我再继续执行
threadSub:已经减到0了,告诉threadAdd开始,等待threadAdd通知我再继续执行
threadAdd:循环了5次了,不继续了,跳出循环让threadSub再继续执行
threadAdd:释放lock
threadSub:循环了5次了,我也不继续了,跳出循环
threadSub:释放lock