• 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秒内获得锁
    收藏文章数量从多到少与“把书读薄”是一个道理
  • 相关阅读:
    【转载】远程桌面协议浅析(VNC/SPICE/RDP)
    【yumex图形安装双击】【转载】CentOS yum的详细使用方法
    【转载】复制文件到已存在的Jar
    黑马程序猿——19,Collections工具类,Arrays工具类,高级for循环,可变參数,静态导入
    在UIView中加入应用下载信息模块
    TCP/IP 寻址
    软考征程之Pv操作
    4:2:0 Video Pixel Formats
    hdu 4908 Task schedule 须要预处理
    sql serve 跨server查询数据方法
  • 原文地址:https://www.cnblogs.com/use-D/p/9740725.html
Copyright © 2020-2023  润新知