简述:这篇文章主要是来了解如何使用ReentrantLock,以及ReentrantLock和Synchronized的对比,基于ReentrantLock的AQS源码的分析在ReentrantLock实现及AQS简析中进行了分析介绍,synchronized实现方式及锁优化 中对synchronized进行了详细的介绍
ReentrantLock是可重入锁,也是独享锁,可重入锁是指:如果当前线程获取到了锁,这个线程可再次进入同步块,独享锁是指,当前锁只能被一个线程锁所拥有
已经有Synchronized了,为什么还要使用Lock?
1、synchronized底层是基于jvm实现的,其加锁和释放锁的操作都是隐式的,其他线程如果没有获取到锁,将进入对象的锁池中,进行等待,这个过程中,没有办法手动将等待的线程释放掉,而ReentrantLock可以手动放弃等待
2、在实际开发场景当中,多个线程对文件进行写操作时,会发生线程,但是如果多个线程之间进行读操作,并不会发生冲突,如果我们都是使用Synchronized来加锁的话,显然会造成一种资源和性能上的浪费,如果这时有一个写锁,只对写操作进行加锁,多线程之间进行读操作时,不会发生冲突。
3、lock操作可以知道当前线程是否获取到了锁,相比较于Synchronized, 显然只是对同步代码进行了加锁操作并不知道我所关心的线程是否获取到了锁。lock更加细粒度的进行了配置
4、当然lock需要手动进行锁的释放,synchronized并不需要进行释放锁
ReentrantLock通用使用方式
Lock lock = new ReentrantLock();
lock.lock();
try{
执行代码逻辑
}catch(Exception e){
}finally{
lock.unlock
}
public class ReenterLockTest {
List<Integer> arrayList = new ArrayList<>();
Lock lock = new ReentrantLock();
public void insert(Thread thread) {
lock.lock();
try{
System.out.println(thread.getName()+" 得到了锁");
for(int i = 0; i < 5; i++) {
arrayList.add(i);
}
}catch (Exception e){
}finally {
System.out.println(thread.getName() +" 释放了锁");
lock.unlock();
}
}
public static void main(String[] args) {
ReenterLockTest test = new ReenterLockTest();
new Thread(()->{
test.insert(Thread.currentThread());
}).start();
new Thread(() ->{
test.insert(Thread.currentThread());
}).start();
}
}
以上代码一定是一个线程执行结束之后,另外一个线程才可以执行
关于lockInterruptibly , 可以中断掉正在阻塞的线程。如果当前线程正在执行,是不能被中断的,如果两个线程都通过lockInterruptibly方式去获取锁,一个获取成功,另外一个失败,对于失败的线程执行interrupt方法,可以中断阻塞。
public class ReentrantLockTest3 {
private Lock lock = new ReentrantLock();
private List<Integer> list = new ArrayList<>();
public void insert(Thread thread) throws InterruptedException{
lock.lockInterruptibly();
try{
System.out.println(thread.getName()+"获得到了锁!");
long startTime = System.currentTimeMillis();
// for(int i = 0; i < 5;i++){
for(; ; ){
if(System.currentTimeMillis() - startTime >= 10000) {
break;
}
}
}finally {
System.out.println(thread.getName()+"执行finally");
lock.unlock();
System.out.println("释放掉了锁!");
}
}
public static void main(String[] args) {
ReentrantLockTest3 test = new ReentrantLockTest3();
InterruptedThread thread1 = new InterruptedThread(test);
InterruptedThread thread2 = new InterruptedThread(test);
thread1.start();
thread2.start();
try{
Thread.sleep(2000);
}catch (InterruptedException e) {
e.printStackTrace();
}
thread2.interrupt();
}
}
class InterruptedThread extends Thread{
private ReentrantLockTest3 test = null;
public InterruptedThread(ReentrantLockTest3 test) {
this.test = test;
}
public void run(){
try{
test.insert(Thread.currentThread());
}catch (InterruptedException e){
System.out.println(Thread.currentThread().getName()+"被中断!");
}
}
}
执行结果
Thread-0获得到了锁!
Thread-1被中断!
Thread-0执行finally
释放掉了锁!
未完~