zoukankan      html  css  js  c++  java
  • 重入锁

    重入锁

    • 重入锁指的是当前线成功获取锁后,如果再次访问该临界区,则不会对自己产生互斥行为。
    • Java中对ReentrantLock和synchronized都是可重入锁,synchronized由jvm实现可重入即使,ReentrantLock都可重入性基于AQS实现。
    • ReentrantLock还提供公平锁和非公平锁两种模式。
    • 重入锁的基本原理是判断上次获取锁的线程是否为当前线程,如果是则可再次进入临界区,如果不是,则阻塞。
    ReentrantLock
    • 在JDK5.0版本之前,重入锁的性能远远好于synchronized关键字,JDK6.0版本之后synchronized 得到了大量的优化,二者性能也不分伯仲,但是重入锁是可以完全替代synchronized关键字的。除此之外,重入锁又自带一系列高逼格UBFF:可中断响应、锁申请等待限时、公平锁。另外可以结合Condition来使用,使其更是逼格满满。
    package cas;
    
    import java.util.concurrent.BlockingDeque;
    import java.util.concurrent.atomic.AtomicInteger;
    import java.util.concurrent.locks.ReentrantLock;
    
    public class MyThread  extends Thread  {
        public static ReentrantLock lock = new ReentrantLock();
        public static int i = 0;
    
        public MyThread(String name) {
            super.setName(name);
        }
    
        @Override
        public void run() {
            for (int j = 0; j < 100; j++) {
                lock.lock();
                try {
                    System.out.println(this.getName() + " " + i);
                    i++;
                } finally {
                    lock.unlock();
                }
            }
        }
    
        /**
         * @param args
         * @throws InterruptedException
         */
        public static void main(String[] args) throws InterruptedException {
            MyThread test1 = new MyThread("thread1");
            MyThread test2 = new MyThread("thread2");
    
            test1.start();
            test2.start();
            test1.join();
            test2.join();
            System.out.println(i);
        }
    }
    
    • 用法上可以看出,与synchronized相比, ReentrantLock就稍微复杂一点。因为必须在finally中进行解锁操作,如果不在 finally解锁,有可能代码出现异常锁没被释放,
    • ReentrantLock并不是一种替代内置加锁的方法,而是作为一种可选择的高级功能。ReentrantLock在功能上更加丰富,它具有可重入、可中断、可限时、公平锁等特点。
    • ReentrantLock 实现了 Lock interface
    • 特点
      • 可重入:可以反复得到相同的一把锁,它有一个与锁相关的获取计数器,如果拥有锁的某个线程再次得到锁,那么获取计数器就加1,然后锁需要被释放两次才能获得真正释放(重入锁)。
      • 与synchronized不同的是,ReentrantLock对中断是有响应的.synchronized一旦尝试获取锁就会一直等待直到获取到锁。
      • 可限时
        • 超时不能获得锁,就返回false,不会永久等待构成死锁
        • 使用lock.tryLock(long timeout, TimeUnit unit)来实现可限时锁,参数为时间和单位。
    public class TryLockTest extends Thread {
    
        public static ReentrantLock lock = new ReentrantLock();
    
        public TryLockTest(String name){
            super(name);
        }
    
        @Override
        public void run() {
            try {
                if (lock.tryLock(5, TimeUnit.SECONDS)) {
                    Thread.sleep(6000);
                } else {
                    System.out.println(this.getName() + " get lock failed");
                }
            } catch (Exception e) {
            } finally {
                if (lock.isHeldByCurrentThread()) {
                    System.out.println("lock.isHeldByCurrentThread: " + this.getName());
                    lock.unlock();
                }
            }
        }
    
        public static void main(String[] args) {
            TryLockTest t1 = new TryLockTest("TryLockTest1");
            TryLockTest t2 = new TryLockTest("TryLockTest2");
    
            t1.start();
            t2.start();
        }
    
    }
    
    实现ReentrantLock公平锁
    • 一般意义上的锁是不公平的,不一定先来的线程能先得到锁,后来的线程就后得到锁。不公平的锁可能会产生饥饿现象。
    • 公平锁的意思就是,这个锁能保证线程是先来的先得到锁。虽然公平锁不会产生饥饿现象,但是公平锁的性能会比非公平锁差很多。
    • synchronized是作为Java关键字是依赖于JVM实现,Java团队应该是优先考虑性能问题,因此synchronized是非公平锁。
    • 使用方法:
    public ReentrantLock(boolean fair) 
    
    public static ReentrantLock fairLock = new ReentrantLock(true);
    
    隐式锁和显式锁
    • 隐式锁:隐式获取锁,synchronized是它的代表,使用者不需要关心其内部锁的获取和释放,所有的锁的相关操作都由具体的关键字完成;
    • 显式锁:显示地获取锁,Lock是它的代表,需要使用者在使用的时候显示地获取和释放锁。
    参考
  • 相关阅读:
    Servlet和Filter的url匹配
    iterator的用法
    python学习笔记
    python的序列之列表
    java开发实战学习笔记3
    java学习笔记4
    Java Java集合
    Struts2中的几个符号
    DbHelper.cs
    做word,excel时需要引用com
  • 原文地址:https://www.cnblogs.com/frankltf/p/10345355.html
Copyright © 2011-2022 走看看