【业务功能篇70】可重入锁与不可重入锁

介绍

本篇介绍的是可重入锁和不可重入锁。可指的是可以,不可指的是不可以。重入指的是重复进入同步作用域。这里的同步作用域可以是同步代码块,也可以是同步方法或者是lock锁同步代码,无论是进入哪一个同步作用域,都意味着同步锁被重复使用。所以重入也有重复使用同步锁的意思。锁指的是同步锁,综上锁述,可重入锁指的是可以重复使用的同步锁。不可重入锁指的是不可以重复使用的同步锁。那么哪些锁是可承认锁,哪些锁是不可承认锁呢?

 【业务功能篇70】可重入锁与不可重入锁_第1张图片

  • 这张表列举了可重入锁与不可重入锁对象,可重复有4个,分别是synchronize,reentrantlock和reentrantreadwritelock.Readlock以及writelocke,不可重入锁没有内置对象,需要我们自己实现。本节的最后我们会去实现一个不可重入锁。下面我们分别来演示可重入锁与不可重入锁。 

【业务功能篇70】可重入锁与不可重入锁_第2张图片

可重入锁

首先演示的是可重入锁,以同步代码为例,写一个同步锁为main.class的同步代码块,在代码块中输出一句话,然后再在同步代码块中写一个同步锁为main.class的同步代码块,目的是测试同步锁是否能重复使用。 

【业务功能篇70】可重入锁与不可重入锁_第3张图片

接着在第二个同步代码块中也输出一句话,观察执行结果。

 从执行结果来看,程序顺利执行,说明同步代码块上的同步锁可重复使用。

【业务功能篇70】可重入锁与不可重入锁_第4张图片

再来看看同步方法的实例,我们知道同步方法分为静态与非静态,这里我们就以静态同步方法为例,定义一个静态同步方法Printa,他的同步锁为类名点class,也就是main.class,然后在Printa方法中说出一句话,接着再定义一个静态同步方法printb,同步锁也为main.class,在printb方法中也说出一句话,然后在printerA A方法中调用printb,目的是测试同步锁是否可重复使用,最后在main方法中调用printa观察执行结果。  

 【业务功能篇70】可重入锁与不可重入锁_第5张图片

 从执行结果来看,程序顺利执行,说明同步方法上的同步锁可重复使用。

【业务功能篇70】可重入锁与不可重入锁_第6张图片

  • 再来看看可重组锁的最后一个例子,创建一个lock锁,new一个reentrantlock对象,调用它的lock方法获取锁,写上try finally代码块,在finally代码块中调用unlook方法释放锁。在try代码块中说出一句话,接着再次调用lock方法获取锁,目的是测试lock锁是否可重复使用。同样的写上try---finally代码块,在finally代码块中调用unlock方法释放锁,最后在try代码块中输出一句话,观察执行结果。  

 【业务功能篇70】可重入锁与不可重入锁_第7张图片

从执行结果来看,程序顺利执行

【业务功能篇70】可重入锁与不可重入锁_第8张图片

说明reentrantlock锁可重复使用,可重入锁演示完毕 


不可重入锁

接下来来看看不可重入锁,因为不可重锁没有内置对象,所以需要我们自己去实现一个不可重入锁。这里我们先理清一下实践的思路,既然是锁,锁以我们首先要实现的是lock接口,这个毋庸置疑,因为lock接口里面,它定义了同步锁的规则,实现它里面的规则,就算是自定义好了一把锁,然后我们需要绑定已经获取到锁的线程,这一步必不可少。哪一个线程获取到了锁,需要记录下来,保证同一时刻只有一个线程拿到锁。 

  • 接着我们要去实现获取锁的方法,也就是实现lock接口中的lock方法。最后我们还需要实现释放锁的方法,也就是实现lock接口中的 unlock方法。

【业务功能篇70】可重入锁与不可重入锁_第9张图片

  • 下面我们就按照这个思路,开始自定义一个不可重入锁,定义一个类。unreentrantlock。实现locker接口。重写lock接口中的方法,它里面一共有6个方法,我们不需要全部都实现,着重实现lock和unlock方法就可以了。定义一个thread类型的属性,用于记录已获取锁的线程。 

 【业务功能篇70】可重入锁与不可重入锁_第10张图片

  • 接下来我们先来实现lock方法,写一个同步锁为this的同步代码块,目的是同一时刻最多只有一个线程执行绑定操作,使用while循环,判断当前是否已经绑定过线程,当已经绑定过线程时,使当前线程等待等待下一次绑定。 


如果当前没有绑定任何线程,则绑定当前线程。

【业务功能篇70】可重入锁与不可重入锁_第11张图片

 

  •  至此lock方法编写完毕,再来编写unlock方法。同样的写上同步锁为this的同步代码块,目的是同一时刻最多只有一个线程执行解绑操作,判断当前线程是否为绑定线程。如果不是直接return,如果是则解绑线程,将thread置为null,并唤醒所有等待的线程,这些被唤醒的线程他们可以继续绑定。

【业务功能篇70】可重入锁与不可重入锁_第12张图片

  • 至此unlook方法编写完毕,整个已经全部编写完毕。下面来使用该锁,还是之前的例子,将可重入锁reentrantlock改为unreentrantlock 

 【业务功能篇70】可重入锁与不可重入锁_第13张图片

运行程序观察执行结果。 

从执行结果来看,程序只打印了第一次获取锁,然后就进入了等待,说明不可重入锁发挥的作用,至此不可重入锁演示完毕。 

你可能感兴趣的:(Java,业务场景实例问题,分布式,java,开发语言,锁)