ReentrantLock说明

Posted use-d

tags:

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

ReentrantLock与synchronized一样都可以用来控制多线线程对共享资源的访问。
synchronized关键字是隐式的获得锁,即进入synchronized方法或者synchronized代码会自动的获得锁,离开同步方法或者同步代码块自动释放锁。
ReentrantLock相对于synchronized来说对锁的操作更加灵活,ReentrantLock可以显示的获得锁 和 释放锁。
对ReentrantLock锁的释放要写在finally代码块下,保证ReentrantLock获得锁后,一定会被释放。
不要将ReentrantLock获得锁的代码写在try代码块下,因为如果ReentrantLock获得锁时方式异常,异常抛出的同时会导致锁无故释放,然后在finally代码块中再释放ReentrantLock锁的话,会报错。
ReentrantLock提供的synchronized关键字不具备的主要特性:
  • 尝试非阻塞的获得锁,当前线程获得锁时,如果锁已经被其他线程获得,可以立即返回false。
  • 能被中断的获得锁,即当线程获得锁后,当前线程被中断后,当前线程可以继续运行。
  • 超时获得锁,在指定时间内获得锁,如果在指定时间内获得锁则返回true,如果在指定时间内获得不到锁,则返回false。
针对上面的三个特定以及ReentrantLock具体的获得锁方法,编写测试代码如下:
测试主方法:
public class MainTest {
    public static void main(String[] args) throws InterruptedException {
        ReentrantLock lock = new ReentrantLock();
        Thread threadA = new Thread(new ThreadA(lock));
        threadA.setName("线程A");
        Thread threadB = new Thread(new ThreadB(lock));
        threadB.setName("线程B");
        threadB.start();
        Thread.sleep(1000);
        threadA.start();
    }
//测试线程B
public class ThreadB implements Runnable{
    private ReentrantLock lock;
    public ThreadB(ReentrantLock lock) {
        this.lock = lock;
    }
    public void run() {
        lock.lock();
        try {
            System.out.println("B对象获得锁");
            Thread.sleep(5000);
        }catch (Exception ex) {
            ex.printStackTrace();
        }finally {
            lock.unlock();
        }
    }
}
}
void lock(),lock方式是阻塞方式的获得锁,B线程获得锁后等待了5秒,在这个过程中A线程尝试获得锁,在B线程等待期间线程A一直处于阻塞状态,直到线程B释放锁后A线程才获得锁。
public class ThreadA  implements Runnable{
    private ReentrantLock lock;
    public ThreadA(ReentrantLock lock) {
        this.lock = lock;
    }
    public void run(){
            lock.lock();
            try {
                System.out.println("A对象获得锁");
            }catch (Exception ex) {
                ex.printStackTrace();
            }finally {
                lock.unlock();
            }
    }
}
指定结果:
B对象获得锁
B对象等待5秒
A对象获得锁
boolean tryLock(),tryLock方式为立即获得锁,如果获得不到则返回false,B线程获得锁后等待了5秒,在这个等待过程中A线程尝试获得锁,结果锁一直被B线程拿着,所以A线程直接返回false,修改测试类A:
public class ThreadA  implements Runnable{
    private ReentrantLock lock;
    public ThreadA(ReentrantLock lock) {
        this.lock = lock;
    }
    public void run(){
            if (lock.tryLock()){
                try {
                    System.out.println("A对象获得锁");
                }catch (Exception ex) {
                    ex.printStackTrace();
                }finally {
                    lock.unlock();
                }
            }
    }
}
指定结果:
B对象获得锁
B对象等待5秒
void lockInterruptibly(),lockInterruptibly获得锁后,如果当前线程获得锁后,代码中进行了interrupt中断后,线程可以继续进行,不会抛出移除,修改测试类A,增加中断代码:
//测试线程A
public class ThreadA  implements Runnable{
    private ReentrantLock lock;

    public ThreadA(ReentrantLock lock) {
        this.lock = lock;
    }

    public void run(){
        try {
            lock.lockInterruptibly();
            try {
                System.out.println("A对象开始中断");
                Thread.currentThread().interrupt();
                System.out.println("A对象结束中断");
            }catch (Exception ex) {
                ex.printStackTrace();
            }finally {
                System.out.println("A对象释放锁");
                lock.unlock();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
指定结果:
B对象获得锁
A对象开始中断
A对象结束中断
A对象释放锁
boolean tryLock(long timeout, TimeUnit unit),tryLock方式为在一段时间内获得锁,如果获得不到则返回false,B线程获得锁后等待了5秒,在这个等待过程中A线程如果在一秒内获得锁,获得锁,则返回true,否则返回false:
public class ThreadA  implements Runnable{
    private ReentrantLock lock;
    public ThreadA(ReentrantLock lock) {
        this.lock = lock;
    }
    public void run(){
        try {
            if (lock.tryLock(6, TimeUnit.SECONDS)){
                try {
                    System.out.println("A对象在6秒内获得锁");
                }catch (Exception ex) {
                    ex.printStackTrace();
                }finally {
                    lock.unlock();
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
指定结果:
B对象获得锁
B对象等待5秒
A对象在6秒内获得锁

 

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

AQS之ReentrantLock分析

ReentrantLock示例说明

以下代码片段 C++ 的说明

为什么JDK代码这样写?final ReentrantLock takeLock = this.takeLock

markdown 打字稿...编码说明,提示,作弊,指南,代码片段和教程文章

ReentrantLock