ReentrantLock介绍
1、可重入锁。可重入锁是指一个线程可以多次获取同一把锁,ReentrantLock和Synchronized都是可重入锁,ReentrantLock主要有两个特性,一个是支持公平锁和非公平锁,一个是可重入,依赖于AQS(AbstractQueuedSynchronizer)实现。
2、可中断锁。可中断锁是指线程尝试获取锁的过程是否可以响应终端。synchronized是不可中断锁,而ReentrantLock则提供了中断功能。
3、公平锁与非公平锁。公平所指多个线程同时尝试获取同一把锁时,获取锁的顺序按照线程达到的顺序,而非公平锁则允许线程“插队”。synchronized是非公平锁,而ReentrantLock的默认实现是非公平锁,但是也可以设置为公平锁。
ReentrantLock继承关系图
ReentrantLock使用示例
public class ReentrantLockDemo {
private static void testLock(){
Lock lock = new ReentrantLock();
lock.lock();
try{
for(int i = 0; i<5; i++){
System.out.println(Thread.currentThread()+"---"+i);
}
}catch (Exception e){
throw e;
}finally {
lock.unlock();
}
}
static class ThreadDemo extends Thread{
@Override
public void run() {
testLock();
}
}
public static void main(String[] args) {
ThreadDemo threadDemo1 = new ThreadDemo();
ThreadDemo threadDemo2 = new ThreadDemo();
ThreadDemo threadDemo3 = new ThreadDemo();
threadDemo1.start();
threadDemo2.start();
threadDemo3.start();
}
运行结果:
Thread[Thread-0,5,main]---0
Thread[Thread-0,5,main]---1
Thread[Thread-0,5,main]---2
Thread[Thread-0,5,main]---3
Thread[Thread-0,5,main]---4
Thread[Thread-2,5,main]---0
Thread[Thread-2,5,main]---1
Thread[Thread-2,5,main]---2
Thread[Thread-2,5,main]---3
Thread[Thread-2,5,main]---4
Thread[Thread-1,5,main]---0
Thread[Thread-1,5,main]---1
Thread[Thread-1,5,main]---2
Thread[Thread-1,5,main]---3
Thread[Thread-1,5,main]---4
}
以上代码是ReentrantLock非公平锁的实现方式,线程获取锁存在随机性。将Lock lock = new ReentrantLock()调整为Lock lock = new ReentrantLock(true)及为公平锁,将会维护一个堵塞队列,按照threadDemo1–>threadDemo2–>threadDemo3的顺序获取锁。
Condition类实现等待通知使用示例
1. notify();notifyAll();唤醒线程是由JVM随机通知的,synchronized加锁相当于整个对象中只有一个Condition对象监视器,所有的线程都注册到它身上,缺少灵活性,
ReentrantLock加Condition可以实现针对单个Condition对象进行特定线程的唤醒。
public class ReentrantLockDemo {
static class TestLock{
Lock lock = new ReentrantLock(true);
//对象监视器a
Condition a = lock.newCondition();
//对象监视器b
Condition b = lock.newCondition();
private void awaitA(){
//操作Condition之前必须要先获取锁
lock.lock();
try{
System.out.println("start"+Thread.currentThread()+"--"+System.currentTimeMillis());
//进入等待状态,释放锁
a.await();
System.out.println("end"+Thread.currentThread()+"--"+System.currentTimeMillis());
}catch (Exception e){
e.printStackTrace();
}finally {
//释放锁
lock.unlock();
}
}
private void awaitB(){
lock.lock();
try{
System.out.println("start"+Thread.currentThread()+"--"+System.currentTimeMillis());
b.await();
System.out.println("end"+Thread.currentThread()+"--"+System.currentTimeMillis());
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
private void signalA(){
//操作Condition之前必须要先获取锁
lock.lock();
try{
//唤醒Condition a
a.signal();
System.out.println(Thread.currentThread()+"--"+System.currentTimeMillis()+"唤醒a");
}catch (Exception e){
e.printStackTrace();
}finally {
//释放锁
lock.unlock();
}
}
private void signalB(){
lock.lock();
try{
b.signal();
System.out.println(Thread.currentThread()+"--"+System.currentTimeMillis()+"唤醒b");
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
}
static class ThreadDemoA extends Thread {
private TestLock testLock;
public ThreadDemoA(TestLock testLock) {
this.testLock = testLock;
}
@Override
public void run() {
//堵塞ThreadDemoA
testLock.awaitA();
}
}
static class ThreadDemoB extends Thread {
private TestLock testLock;
public ThreadDemoB(TestLock testLock) {
this.testLock = testLock;
}
@Override
public void run() {
//堵塞ThreadDemoB
testLock.awaitB();
}
}
public static void main(String[] args) throws InterruptedException{
TestLock testLock = new TestLock();
ThreadDemoA threadDemoA = new ThreadDemoA(testLock);
threadDemoA.setName("threadDemoA");
ThreadDemoB threadDemoB = new ThreadDemoB(testLock);
threadDemoB.setName("threadDemoB");
threadDemoA.start();
threadDemoB.start();
Thread.sleep(2000);
testLock.signalA();
Thread.sleep(2000);
testLock.signalB();
}
}
运行结果:
startThread[threadDemoA,5,main]--1591258392692
startThread[threadDemoB,5,main]--1591258392701
Thread[main,5,main]--1591258394689唤醒a
endThread[threadDemoA,5,main]--1591258394689
Thread[main,5,main]--1591258396689唤醒b
endThread[threadDemoB,5,main]--1591258396720
ReentrantLock类公平锁与非公平锁
1.公平锁表示线程获取锁的顺序是按照线程加锁的顺序来分配的,即FIFO先进先出的顺序。
2.非公平锁是一种锁的抢夺机制,是随机获取锁的,即先来的不一定先得到锁,有些线程
可能一直得不到锁,所以是非公平的。
//公平锁
Lock fairLock = new ReentrantLock(true);
//非公平锁(构造方法不传参,默认创建非公平锁)
Lock unFairLock = new ReentrantLock(false);
ReentrantLock类常用方法
1.int getHoldCount方法,查询当前线程保持此锁定的个数,ReentrantLock是可重入锁,获得锁之后,调用的内部方法还可以再次获得锁。
public class ReentrantLockDemo {
private ReentrantLock lock = new ReentrantLock();
public void serviceMethod1(){
try {
lock.lock();
System.out.println("第一层锁!");
System.err.println("serviceMethod1保持锁的个数"+lock.getHoldCount());
//serviceMethod2方法也需要获得锁,需要加锁,
// 在serviceMethod2方法下,保持的锁个数是2个
serviceMethod2();
} finally {
lock.unlock();
}
}
public void serviceMethod2(){
try {
//ReentrantLock是可重入锁,所以serviceMethod2依然可以再次加锁
//Sychronized也是可重入锁
lock.lock();
System.out.println("第二层锁!");
System.err.println("serviceMethod2保持锁的个数"+lock.getHoldCount());
} finally {
lock.unlock();
}
}
public static void main(String[] args) {
ReentrantLockDemo reentrantLockDemo = new ReentrantLockDemo();
reentrantLockDemo.serviceMethod1();
}
}
第一层锁!
第二层锁!
serviceMethod1保持锁的个数1
serviceMethod2保持锁的个数2
2.int getQueueLength方法,当前等待获取此锁的线程数。
public class ReentrantLockDemo {
private static ReentrantLock lock = new ReentrantLock();
public void serviceMethod1(){
try {
lock.lock();
System.err.println("线程休眠10s,未释放锁");
//sleep方法执行完不释放锁,wait方法执行完释放锁
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public static void main(String[] args) throws InterruptedException {
ReentrantLockDemo reentrantLockDemo = new ReentrantLockDemo();
Runnable runnable = new Runnable() {
@Override
public void run() {
reentrantLockDemo.serviceMethod1();
}
};
for(int i = 0; i<10; i++){
//创建10个线程,第1个线程阻塞,其他9个等待获取锁
Thread thread = new Thread(runnable);
thread.start();
}
Thread.sleep(2000);
System.err.println("当前等待获取锁的线程数:"+lock.getQueueLength());
}
}
线程休眠10s,未释放锁
当前等待获取锁的线程数:9
3.int getWaitQueueLength方法是返回等待与此锁定相关条件Condition 的线程估计数,获取Condition条件下的等待线程数
public class ReentrantLockDemo {
private static ReentrantLock lock = new ReentrantLock();
private static Condition condition = lock.newCondition();
public void serviceMethod1(){
try {
lock.lock();
System.err.println("执行await方法,等待唤醒,释放锁");
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public static void main(String[] args) throws InterruptedException {
ReentrantLockDemo reentrantLockDemo = new ReentrantLockDemo();
Runnable runnable = new Runnable() {
@Override
public void run() {
reentrantLockDemo.serviceMethod1();
}
};
for(int i = 0; i<10; i++){
//创建10个线程去执行await方法
Thread thread = new Thread(runnable);
thread.start();
}
Thread.sleep(2000);
try {
//涉及await等先获取锁再操作
lock.lock();
System.err.println("condition监视器下等待唤醒的线程数:"+lock.getWaitQueueLength(condition));
//全部唤醒
condition.signalAll();
} finally {
lock.unlock();
}
}
}
执行await方法,等待唤醒,释放锁
执行await方法,等待唤醒,释放锁
执行await方法,等待唤醒,释放锁
执行await方法,等待唤醒,释放锁
执行await方法,等待唤醒,释放锁
执行await方法,等待唤醒,释放锁
执行await方法,等待唤醒,释放锁
执行await方法,等待唤醒,释放锁
执行await方法,等待唤醒,释放锁
执行await方法,等待唤醒,释放锁
condition监视器下等待唤醒的线程数:10
4.boolean hasQueuedThread(Thread thread)方法,是查询thread线程是否等待获取锁,hasQueuedThreads是查询是否有线程等待获取锁
public class ReentrantLockDemo {
private static ReentrantLock lock = new ReentrantLock();
private static Condition condition = lock.newCondition();
public void serviceMethod1(){
try {
lock.lock();
System.err.println("休眠10s,不释放锁");
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public static void main(String[] args) throws InterruptedException {
ReentrantLockDemo reentrantLockDemo = new ReentrantLockDemo();
Runnable runnable = new Runnable() {
@Override
public void run() {
reentrantLockDemo.serviceMethod1();
}
};
Thread threada = new Thread(runnable);
threada.start();
threada.sleep(1000);
Thread threadb = new Thread(runnable);
threadb.start();
threadb.sleep(1000);
System.err.println("threada线程是否正在等到获取锁:"+lock.hasQueuedThread(threada));
System.err.println("threadb线程是否正在等到获取锁:"+lock.hasQueuedThread(threadb));
System.err.println("是否有线程正在等到获取锁:"+lock.hasQueuedThreads());
}
}
休眠10s,不释放锁
threada线程是否正在等到获取锁:false
threadb线程是否正在等到获取锁:true
是否有线程正在等到获取锁:true
5.boolean hasWaiters方法是查询某Condition 条件下是否有线程正在等待唤醒
public class ReentrantLockDemo {
private static ReentrantLock lock = new ReentrantLock();
private static Condition condition = lock.newCondition();
public void serviceMethod1(){
try {
lock.lock();
System.err.println("执行await方法,释放锁");
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public static void main(String[] args) throws InterruptedException {
ReentrantLockDemo reentrantLockDemo = new ReentrantLockDemo();
Runnable runnable = new Runnable() {
@Override
public void run() {
reentrantLockDemo.serviceMethod1();
}
};
Thread threada = new Thread(runnable);
threada.start();
threada.sleep(1000);
Thread threadb = new Thread(runnable);
threadb.start();
threadb.sleep(1000);
try {
lock.lock();
System.err.println("condition监视器下是否有线程正在等待唤醒:"+lock.hasWaiters(condition));
System.err.println("condition监视器下正在等待唤醒线程数:"+lock.getWaitQueueLength(condition));
condition.signalAll();
} finally {
lock.unlock();
}
}
}
执行await方法,释放锁
执行await方法,释放锁
condition监视器下是否有线程正在等待唤醒:true
condition监视器下正在等待唤醒线程数:2
6.boolean isFair方法是判断是不是公平锁。默认状态创建的锁都是非公平锁
7.boolean isHeldByCurrentThread方法查询当前是否获取该锁(保持此锁定),boolean isLocked方法查询此锁是否被获取,是否被任意线程获取了此锁,保持此锁定
public class ReentrantLockDemo {
private static ReentrantLock lock = new ReentrantLock();
private static Condition condition = lock.newCondition();
public void serviceMethod1(){
try {
lock.lock();
System.err.println("执行serviceMethod1方法,当前线程是否已获取锁:"+lock.isHeldByCurrentThread());
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void serviceMethod2(){
System.err.println("执行serviceMethod2方法,当前线程是否已获取锁:"+lock.isHeldByCurrentThread());
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws InterruptedException {
ReentrantLockDemo reentrantLockDemo = new ReentrantLockDemo();
Runnable runnable = new Runnable() {
@Override
public void run() {
reentrantLockDemo.serviceMethod1();
}
};
Thread threada = new Thread(
new Runnable() {
@Override
public void run() {
reentrantLockDemo.serviceMethod1();
}
}
);
threada.start();
threada.sleep(1000);
Thread threadb = new Thread(
new Runnable() {
@Override
public void run() {
reentrantLockDemo.serviceMethod2();
}
}
);
threadb.start();
threadb.sleep(1000);
System.out.println("lock锁是否被线程获取:"+lock.isLocked());
}
}
执行serviceMethod1方法,当前线程是否已获取锁:true
执行serviceMethod2方法,当前线程是否已获取锁:false
lock锁是否被线程获取:true
8.void lockInterruptibly方法是获取锁,如果当前线程未被中断(更改中断标识)则持续等待获取锁,如果当前线程被中断则抛异常。
void lock方法是获取锁,被中断也持续获取锁。
public class ReentrantLockDemo {
private static ReentrantLock lock = new ReentrantLock();
private static Condition condition = lock.newCondition();
public void serviceMethod1(String threadName){
try{
System.err.println(threadName+"线程尝试获取锁:");
lock.lockInterruptibly();//结果如【结果1】所示
//lock.lock();//结果如【结果2】所示
System.err.println(threadName+"线程已获取锁:");
for(int i = 0; i < Integer.MAX_VALUE/100;i++){
continue;
}
System.err.println(threadName+"线程已释放锁:");
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public static void main(String[] args) throws InterruptedException {
ReentrantLockDemo reentrantLockDemo = new ReentrantLockDemo();
Thread threada = new Thread(
new Runnable() {
@Override
public void run() {
reentrantLockDemo.serviceMethod1("threada");
}
}
);
threada.start();
threada.sleep(1000);
Thread threadb = new Thread(
new Runnable() {
@Override
public void run() {
reentrantLockDemo.serviceMethod1("threadb");
}
}
);
threadb.start();
//尝试获取锁过程中将线程标记中断标识,线程抛异常
threadb.interrupt();
}
}
结果1:
threada线程尝试获取锁:
threada线程已获取锁:
threada线程已释放锁:
threadb线程尝试获取锁:
java.lang.InterruptedException
at java.base/java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(AbstractQueuedSynchronizer.java:1261)
at java.base/java.util.concurrent.locks.ReentrantLock.lockInterruptibly(ReentrantLock.java:317)
at com.example.demo.ReentrantLockDemo.serviceMethod1(ReentrantLockDemo.java:13)
at com.example.demo.ReentrantLockDemo$2.run(ReentrantLockDemo.java:43)
at java.base/java.lang.Thread.run(Thread.java:834)
结果2:
threada线程尝试获取锁:
threada线程已获取锁:
threada线程已释放锁:
threadb线程尝试获取锁:
threadb线程已获取锁:
threadb线程已释放锁:
9.boolean tryLock方法在调用时,如果锁未被其他线程保持,则获取锁,返回true;否则不获取锁,返回false。演示该方法
boolean tryLock(long timeout,TimeUnit unit)方法是在给定时间内,持续尝试获取锁,如果锁未被其他线程保持,且当前线程未被中断,则获取锁。不演示该方法
public class ReentrantLockDemo {
private static ReentrantLock lock = new ReentrantLock();
private static Condition condition = lock.newCondition();
public void serviceMethod1(){
try{
System.err.println(Thread.currentThread().getName()+"线程尝试获取锁:");
//尝试获取锁,获取成功返回true
if(lock.tryLock()){
System.err.println(Thread.currentThread().getName()+"线程已获取锁:");
}else{
System.err.println(Thread.currentThread().getName()+"线程未获取锁:");
}
System.err.println(Thread.currentThread().getName()+"线程已结束:");
} catch (Exception e) {
e.printStackTrace();
} finally {
//如果当前线程持有锁,则释放
if(lock.isHeldByCurrentThread()){
lock.unlock();
System.err.println(Thread.currentThread().getName()+"线程已释放锁:");
}
}
}
public static void main(String[] args) throws InterruptedException {
ReentrantLockDemo reentrantLockDemo = new ReentrantLockDemo();
Thread threada = new Thread(
new Runnable() {
@Override
public void run() {
reentrantLockDemo.serviceMethod1();
}
}
);
threada.setName("threada");
threada.start();
Thread threadb = new Thread(
new Runnable() {
@Override
public void run() {
reentrantLockDemo.serviceMethod1();
}
}
);
threadb.setName("threadb");
threadb.start();
}
}
threada线程尝试获取锁:
threadb线程尝试获取锁:
threada线程已获取锁:
threadb线程未获取锁:
threada线程已结束:
threadb线程已结束:
threada线程已释放锁:
10.void awaitUninterruptibly()方法:线程在调用condition.await()后处于await状态,此时调用thread.interrupt()会报错,但是使用condition.awaitUninterruptibly()后,调用thread.interrupt()则不会报错。
public class ReentrantLockDemo {
private static ReentrantLock lock = new ReentrantLock();
private static Condition condition = lock.newCondition();
public void serviceMethod1(){
try{
if(lock.tryLock()){
System.err.println(Thread.currentThread().getName()+"线程已获取锁,执行await方法。");
condition.awaitUninterruptibly();
System.err.println(Thread.currentThread().getName()+"线程await方法结束。");
}else{
System.err.println(Thread.currentThread().getName()+"线程未获取锁:");
}
System.err.println(Thread.currentThread().getName()+"线程已结束:");
} catch (Exception e) {
e.printStackTrace();
} finally {
//如果当前线程持有锁,则释放
if(lock.isHeldByCurrentThread()){
lock.unlock();
System.err.println(Thread.currentThread().getName()+"线程已释放锁:");
}
}
}
public void serviceMethod2(){
try{
if(lock.tryLock()){
System.err.println(Thread.currentThread().getName()+"线程已获取锁,执行signalAll方法。");
condition.signalAll();
System.err.println(Thread.currentThread().getName()+"线程signalAll方法结束。");
}else{
System.err.println(Thread.currentThread().getName()+"线程未获取锁:");
}
System.err.println(Thread.currentThread().getName()+"线程已结束:");
} catch (Exception e) {
e.printStackTrace();
} finally {
//如果当前线程持有锁,则释放
if(lock.isHeldByCurrentThread()){
lock.unlock();
System.err.println(Thread.currentThread().getName()+"线程已释放锁:");
}
}
}
public static void main(String[] args) throws InterruptedException {
ReentrantLockDemo reentrantLockDemo = new ReentrantLockDemo();
Thread threada = new Thread(
new Runnable() {
@Override
public void run() {
reentrantLockDemo.serviceMethod1();
}
}
);
threada.setName("threada");
threada.start();
Thread.sleep(3000);
threada.interrupt();
Thread.sleep(3000);
reentrantLockDemo.serviceMethod2();
}
}
threada线程已获取锁,执行await方法。
main线程已获取锁,执行signalAll方法。
main线程signalAll方法结束。
main线程已结束:
main线程已释放锁:
threada线程await方法结束。
threada线程已结束:
threada线程已释放锁:
11.boolean awaitUntil(Date deadline)方法,是在deadline时间到期后,自动唤醒,不会一直等待,await会一直等待,直到唤醒。
public class ReentrantLockDemo {
private static ReentrantLock lock = new ReentrantLock();
private static Condition condition = lock.newCondition();
public void serviceMethod1(){
try{
if(lock.tryLock()){
Calendar calendar = Calendar.getInstance();
calendar.setTime(new Date());
System.err.println(Thread.currentThread().getName()+"线程已获取锁,执行await方法,时间:"+calendar.getTime());
calendar.add(Calendar.SECOND,10);
condition.awaitUntil(calendar.getTime());
System.err.println(Thread.currentThread().getName()+"线程await方法结束,时间:"+new Date());
}else{
System.err.println(Thread.currentThread().getName()+"线程未获取锁:");
}
System.err.println(Thread.currentThread().getName()+"线程已结束:");
} catch (Exception e) {
e.printStackTrace();
} finally {
//如果当前线程持有锁,则释放
if(lock.isHeldByCurrentThread()){
lock.unlock();
System.err.println(Thread.currentThread().getName()+"线程已释放锁:");
}
}
}
public void serviceMethod2(){
try{
if(lock.tryLock()){
System.err.println(Thread.currentThread().getName()+"线程已获取锁,执行signalAll方法。");
condition.signalAll();
System.err.println(Thread.currentThread().getName()+"线程signalAll方法结束,时间:"+new Date());
}else{
System.err.println(Thread.currentThread().getName()+"线程未获取锁:");
}
System.err.println(Thread.currentThread().getName()+"线程已结束:");
} catch (Exception e) {
e.printStackTrace();
} finally {
//如果当前线程持有锁,则释放
if(lock.isHeldByCurrentThread()){
lock.unlock();
System.err.println(Thread.currentThread().getName()+"线程已释放锁:");
}
}
}
public static void main(String[] args) throws InterruptedException {
ReentrantLockDemo reentrantLockDemo = new ReentrantLockDemo();
Thread threada = new Thread(
new Runnable() {
@Override
public void run() {
reentrantLockDemo.serviceMethod1();
}
}
);
threada.setName("threada");
threada.start();
Thread.sleep(3000);
reentrantLockDemo.serviceMethod2();
}
}
threada线程已获取锁,执行await方法,时间:Sun Jun 28 15:23:19 CST 2020
main线程已获取锁,执行signalAll方法。
main线程signalAll方法结束,时间:Sun Jun 28 15:23:22 CST 2020
main线程已结束:
threada线程await方法结束,时间:Sun Jun 28 15:23:22 CST 2020
threada线程已结束:
threada线程已释放锁:
main线程已释放锁:
ReentrantReadWriteLock类
ReentrantLock类具有完全排他的效果,效率非常慢,ReentrantReadWriteLock提供了读写锁,一个读锁(共享锁),一个写锁(排他锁),多个读锁之间不互斥,多个写锁之间互斥,读锁与写锁之间互斥。
1.读读共享:一个线程获取了读锁,另一个线程可以继续同时获取此读锁
2.写写互斥:一个线程获取了写锁,一定要释放之后其他线程才能获取此写锁。
3.写读互斥/读写互斥:一个线程获取了读锁,未释放之前不能获取此写锁,或者一个线程获取写锁之后,未释放其他线程不能获取此读锁
示例读写互斥:
public class ReentrantLockDemo {
//声明读写锁
private static ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
public void serviceMethod1() {
try {
System.err.println(Thread.currentThread().getName() + "线程尝试获取读锁:" + new Date());
//获取读锁,进而加锁
lock.readLock().lock();
System.err.println(Thread.currentThread().getName() + "线程已获取读锁:" + new Date());
//休眠3s不释放锁
Thread.sleep(3000);
} catch (Exception e) {
e.printStackTrace();
} finally {
//获取读锁,同时释放锁
lock.readLock().unlock();
System.err.println(Thread.currentThread().getName() + "线程已释放读锁:" + new Date());
}
}
public void serviceMethod2() {
try {
System.err.println(Thread.currentThread().getName() + "线程尝试获取写锁:" + new Date());
//获取写锁,进而加锁
lock.writeLock().lock();
System.err.println(Thread.currentThread().getName() + "线程已获取写锁:" + new Date());
} catch (Exception e) {
e.printStackTrace();
} finally {
//获取写锁,同时释放锁
lock.writeLock().unlock();
System.err.println(Thread.currentThread().getName() + "线程已释放读锁:" + new Date());
}
}
public static void main(String[] args) throws InterruptedException {
ReentrantLockDemo reentrantLockDemo = new ReentrantLockDemo();
Thread threada = new Thread(
new Runnable() {
@Override
public void run() {
reentrantLockDemo.serviceMethod1();
}
}
);
threada.setName("threada");
threada.start();
Thread.sleep(1000);
Thread threadb = new Thread(
new Runnable() {
@Override
public void run() {
reentrantLockDemo.serviceMethod2();
}
}
);
threadb.setName("threadb");
threadb.start();
}
}
threada线程尝试获取读锁:Sun Jun 28 23:55:59 CST 2020
threada线程已获取读锁:Sun Jun 28 23:55:59 CST 2020
threadb线程尝试获取写锁:Sun Jun 28 23:56:00 CST 2020
threada线程已释放读锁:Sun Jun 28 23:56:02 CST 2020
//只有在释放读锁之后,才能获取写锁,读写/写读互斥
threadb线程已获取写锁:Sun Jun 28 23:56:02 CST 2020
threadb线程已释放读锁:Sun Jun 28 23:56:02 CST 2020
总结
Lock对象可以将synchronized关键字代替,其特有的属性是synchronized关键字不具备的,Lock对象是synchronized关键字的进阶,在jdk中并发包中大量类都是使用的Loc接口作为处理同步的方式。