对于 ReentrantLock 有很多的名称:同步锁,重入锁,独占锁,公平锁
白话来讲:理解方式就是公平锁,排着队一个一个的来,谁等的时间最长谁就先执行。非公平锁就是不排队,谁先抢到谁就执行
可重入
什么是可重入?他的作用是什么?可重入(也有叫重入锁的)就是,当一个持有锁的线程,在释放锁之前,被重复访问或者访问了此锁的其他方法,那么这个线程不需要进行抢占锁,只会被记录重入次数,重入锁的作用就是为了防止死锁现象
独占锁
独占锁顾名思义, 就是一个线程获得了锁,别的线程就不能获得锁,必须等锁释放了,才能可能获取到锁
公平锁
什么是公平锁?为啥说 ReentrantLock 自带公平锁机制呢?我们接着往下看!可以点开 ReentrantLock 的源码看下,我们创建的 ReentrantLock 对象完整的应该是这个样子的,ReentrantLock 默认使用的是非公平锁,如果不传参数,默认的是 false,然后看下边第二段 ReentrantLock(boolean fair),意思是传入 true 或者 false ,传入 true 就是开启公平锁机制
1、不同线程执行同一个lock(),后执行的那个线程的lock()方法会阻塞
lock();获取锁。
如果锁未被另一个线程持有,则获取锁,并立即返回,将锁持有计数设置为1。
如果当前线程已经持有锁,那么持有计数将增加1,并且该方法立即返回。
如果锁由另一个线程持有,则当前线程出于线程调度目的而被禁用,并且处于休眠状态,直到获取了锁为止,此时锁持有计数被设置为1。
public class Test1 {
private static ReentrantLock connectedLock = new ReentrantLock();
private static Condition connectedCondition = connectedLock.newCondition();
public static void main(String[] args) throws Exception {
// 线程1
new Thread(() -> {
try {
Thread.sleep(1000);
connectedLock.lock();
System.out.println("-----1");
Thread.sleep(5000);
System.out.println("-----2");
} catch (Exception e) {
e.printStackTrace();
} finally {
connectedLock.unlock();
System.out.println("-----3");
}
}).start();
// 线程2
new Thread(() -> {
try {
Thread.sleep(1500);
connectedLock.lock();
System.out.println("=====1");
} catch (Exception e) {
e.printStackTrace();
} finally {
connectedLock.unlock();
System.out.println("=====2");
}
}).start();
}
}
执行结果:
-----1
-----2
-----3
=====1
=====2
2、ReentrantLock通过Condition能够更加精细的控制多线程的休眠与唤醒。
ReentrantLock通过Condition能够更加精细的控制多线程的休眠与唤醒。_小百菜的博客-CSDN博客
public class Test2 {
private static ReentrantLock connectedLock = new ReentrantLock();
private static Condition connectedCondition = connectedLock.newCondition();
public static void main(String[] args) throws Exception {
// 线程1
new Thread(() -> {
try {
Thread.sleep(1000);
connectedLock.lock();
System.out.println("-----1");
Thread.sleep(5000);
System.out.println("-----2");
} catch (Exception e) {
e.printStackTrace();
} finally {
connectedLock.unlock();
System.out.println("-----3");
}
}).start();
// 线程2
new Thread(() -> {
try {
Thread.sleep(1500);
connectedLock.lock();
System.out.println("=====1");
connectedCondition.signalAll();//不会阻塞
System.out.println("=====2");
} catch (Exception e) {
e.printStackTrace();
} finally {
connectedLock.unlock();
System.out.println("=====3");
}
}).start();
}
}
运行结果:
-----1
-----2
-----3
=====1
=====2
=====3
注意:当前线程处于等待时,其他线程的其中一个线程会抢到锁,抢到锁的那个线程lock()不再阻塞,会往下执行。
public class Test3 {
private static ReentrantLock connectedLock = new ReentrantLock();
private static Condition connectedCondition = connectedLock.newCondition();
public static void main(String[] args) throws Exception {
// 线程1
new Thread(() -> {
try {
Thread.sleep(1000);
connectedLock.lock();
System.out.println("-----1");
Thread.sleep(5000);
System.out.println("-----2");
// await 使当前线程等待,直到发出信号或中断,或者经过指定的等待时间。
// 注意:当前线程处于等待时,其他线程的其中一个线程会抢到锁,抢到锁的那个线程lock()不再阻塞,会往下执行。
connectedCondition.await(20, TimeUnit.SECONDS);//阻塞指定时间,其他线程唤醒会提前结束
System.out.println("-----3");
} catch (Exception e) {
e.printStackTrace();
} finally {
connectedLock.unlock();
System.out.println("-----4");
}
}).start();
// 线程2
new Thread(() -> {
try {
Thread.sleep(1500);
connectedLock.lock();
System.out.println("=====1");
connectedCondition.signalAll();//不会阻塞
System.out.println("=====2");
} catch (Exception e) {
e.printStackTrace();
} finally {
connectedLock.unlock();
System.out.println("=====3");
}
}).start();
}
}
运行结果:
-----1
-----2
=====1
=====2
=====3
-----3
-----4