ReentrantLock

Posted whalesea

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ReentrantLock相关的知识,希望对你有一定的参考价值。

一、将ReentrantLock和synchronized进行比较

1、synchronized和ReentrantLock都是独占锁,不同的是synchronized加锁和解锁过程自动进行;ReentrantLock需手动加锁解锁。

2、synchronized和ReentrantLock都可重入,不同的是synchronized自动进行,不必担心最后是否释放锁;但是ReentrantLock手动进行,加锁和解锁的次数需要完全一样。

可重入演示:

            synchronized (this){
                System.out.println(Thread.currentThread().getName()+" :synchronized代码块start.....");
                System.out.println(Thread.currentThread().getName()+" :synchronized代码块sleep.....");
                Thread.sleep(2000);
                System.out.println(Thread.currentThread().getName()+" :synchronized代码块voer!!!");
                synchronized (this){
                    System.out.println("重入");
                }
            }

3、相应中断:synchronized不可相应中断;ReentrantLock可以。

 

二、ReentrantLock的特性

1、简单演示

public class ReentrantLockRunnable implements Runnable{
    private ReentrantLock lock = new ReentrantLock(true);
  
    @Override
    public void run() {
        try{
            while (true){
                lock.lock();
                
                System.out.println(Thread.currentThread().getName()+"ReenTrant 已加锁");
                Thread.sleep(2000);
                System.out.println(Thread.currentThread().getName()+"sleep.....");
            }

        }catch (InterruptedException e){
            System.out.println("中断");
            e.printStackTrace();
        }finally {
                lock.unlock();
            System.out.println(Thread.currentThread().getName()+"ReenTrant 锁已释放!!!!");
        }


    }
}


import lombok.SneakyThrows;

public class ReentrantLockDemo {

    @SneakyThrows
    public static void main(String[] args){
        Runnable lock = new ReentrantLockRunnable();
        Thread thread1 = new Thread(lock);
        Thread thread2 = new Thread(lock);

        thread1.start();
        thread2.start();
    }

}

 

结果:

Thread-0ReenTrant 已加锁
Thread-0sleep.....
Thread-0ReenTrant 锁已释放!!!!
Thread-1ReenTrant 已加锁
Thread-1sleep.....
Thread-1ReenTrant 锁已释放!!!!

 

2、公平锁

线程获取锁的顺序按照调用lock方法的顺序,慎用!

private ReentrantLock lock = new ReentrantLock(true);

只需要添加true参数即可;不添加或者false参数既是不公平锁,随机获取。

3、响应中断

import java.util.concurrent.locks.ReentrantLock;

public class ReentrantLockRunnable implements Runnable{
    private ReentrantLock lock = new ReentrantLock(true);
    private static int count = 0;
    @Override
    public void run() {
        try{
            while (true){
                lock.lock();
                count++;
                System.out.println(Thread.currentThread().getName()+"ReenTrant 已加锁");
                Thread.sleep(2000);
                System.out.println(Thread.currentThread().getName()+"sleep.....");
            }

        }catch (InterruptedException e){
            System.out.println("中断");
//            e.printStackTrace();
        }finally {
            for(int i=0;i<count;i++){
                lock.unlock();
            }

            System.out.println(Thread.currentThread().getName()+"ReenTrant 锁已释放!!!!");
        }


    }
}


import lombok.SneakyThrows;

public class ReentrantLockDemo {

    @SneakyThrows
    public static void main(String[] args){
        Runnable lock = new ReentrantLockRunnable();
        Thread thread1 = new Thread(lock);
        Thread thread2 = new Thread(lock);

        thread1.start();
        thread2.start();
        Thread.sleep(5000);
        thread1.interrupt();
    }

}

结果:

Thread-0ReenTrant 已加锁
Thread-0sleep.....
Thread-0ReenTrant 已加锁
Thread-0sleep.....
Thread-0ReenTrant 已加锁
中断
Thread-0ReenTrant 锁已释放!!!!
Thread-1ReenTrant 已加锁
Thread-1sleep.....
Thread-1ReenTrant 已加锁
Thread-1sleep.....
Thread-1ReenTrant 已加锁
Thread-1sleep.....
Thread-1ReenTrant 已加锁
Thread-1sleep.....
。。。。。持续运行

上述代码中加锁几次释放几次,现在把finally中的代码修改:

finally {
            
            lock.unlock();
            System.out.println(Thread.currentThread().getName()+"ReenTrant 锁已释放!!!!");
        }

结果:

Thread-0ReenTrant 已加锁
Thread-0sleep.....
Thread-0ReenTrant 已加锁
Thread-0sleep.....
Thread-0ReenTrant 已加锁
中断
Thread-0ReenTrant 锁已释放!!!!

Thread-1线程无法进入继续运行,因为锁没有完全释放。加了三次锁,只释放了两次。

5、限时等待

使用tryLock带替lock,设置等待时间,如果取得锁则返回true,如果没有取得则返回false。无参默认不等待,直接返回结果。

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

public class ReentrantLockDome2 implements Runnable{
    private ReentrantLock lock = new ReentrantLock();

    @Override
    public void run() {

        try{
            if (lock.tryLock(1, TimeUnit.SECONDS)){
                System.out.println(Thread.currentThread().getName()+": 已加锁!");
                
                System.out.println(Thread.currentThread().getName()+": sleep....");
                TimeUnit.SECONDS.sleep(5);
            }else{
                System.out.println(Thread.currentThread().getName()+": come here!");
                System.out.println(Thread.currentThread().getName()+": over!");
            }
        }catch (InterruptedException e){
            System.out.println(Thread.currentThread().getName()+":中断");
        }finally {
            if(lock.isHeldByCurrentThread()){//此锁是否由当前线程持有
                lock.unlock();
                System.out.println(Thread.currentThread().getName()+": 释放锁!");
            }

        }


    }

    public static void main(String[] args){
        ReentrantLockDome2 reentrantLockDome2 = new ReentrantLockDome2();
        Thread thread1 = new Thread(reentrantLockDome2);
        Thread thread2 = new Thread(reentrantLockDome2);

        thread1.start();
        thread2.start();

    }
}

结果:

Thread-0: 已加锁!
Thread-0: sleep....
Thread-1: come here!
Thread-1: over!
Thread-0: 释放锁!

 

lock.lock();

以上是关于ReentrantLock的主要内容,如果未能解决你的问题,请参考以下文章

ReentrantLock源码分析

Java ReEntrantLock 之 Condition条件(Java代码实战-002)

ReentrantLock使用示例

互斥锁 & 共享锁

ReentrantLock实现原理深入探究

[图解Java]ReentrantLock重入锁