java---ReentrantLock

简介: ReentrantLock介绍java多线程中可以使用synchronized关键字来实现线程间同步互斥,但在jdk1.5中新增加了ReentrantLock类也能实现同样的效果。

ReentrantLock介绍

java多线程中可以使用synchronized关键字来实现线程间同步互斥,但在jdk1.5中新增加了ReentrantLock类也能实现同样的效果。

ReentrantLock:表示重入锁,它是唯一一个实现了Lock接口的类。重入锁指的是 线程在获得锁之后,再次获取该锁不需要阻塞,而是直接关联一次计数器增加重入次;

Lock常用方法

网络异常,图片无法展示
|

ReentrantLock.lock() 这个是reentrantLock获取锁的入口

public void lock() {
        sync.lock();
    }

网络异常,图片无法展示
|

sync实际上是一个抽象的静态内部类,它继承了AQS来实现重入锁的逻辑,我们前面说过AQS是一个同步队列,它能够实现线程的阻塞以及唤醒,但它并不具备 业务功能,所以在不同的同步场景中,会继承AQS来实现对应场景的功能 Sync有两个具体的实现类,

什么是AQS?

AQS即AbstractQueuedSynchronizer,是一个用于构建锁和同步器的框架。它能降低构建锁和同步器的工作量,还可以避免处理多个位置上发生的竞争问题。在基于AQS构建的同步器中,只可能在一个时刻发生阻塞,从而降低上下文切换的开销,并提高吞吐量

AQS支持独占锁(exclusive)和共享锁(share)两种模式。

  • 独占锁:只能被一个线程获取到(Reentrantlock)
  • 共享锁:可以被多个线程同时获取(CountDownLatch,ReadWriteLock).

分别是:

NofairSync:非公平锁,可以存在抢占锁的功能,也就是说不管当前队列上是否存在其他 线程等待,新线程都有机会抢占锁

FailSync:公平锁,所有线程严格按照FIFO来获取锁

公平锁示例

谁等的时间最长,谁就先获取锁

public class ReentrantLockTest {
    static Lock lock = new ReentrantLock(true);
    public static void main(String[] args) throws InterruptedException {
        for(int i=0;i<5;i++){
            new Thread(new ThreadDemo(i)).start();
        }
    }
    static class ThreadDemo implements Runnable {
        Integer id;
        public ThreadDemo(Integer id) {
            this.id = id;
        }
        @Override
      public void run() {
            try {
                TimeUnit.MILLISECONDS.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            for(int i=0;i<2;i++){
                lock.lock();
                System.out.println("获得锁的线程:"+id);
                lock.unlock();
            }
        }
    }
}

非公平锁示例

非公平锁那就随机的获取,谁运气好,cpu时间片轮到哪个线程,哪个线程就能获取锁

static Lock lock = new ReentrantLock(false);//参数为false,当然我们也可以不写,默认就是false

ReentrantLock和synchronized对比

(1)synchronized是独占锁,加锁和解锁的过程自动进行,易于操作,但不够灵活。ReentrantLock也是独占锁,加锁和解锁的过程需要手动进行,不易操作,但非常灵活。

(2)synchronized可重入,因为加锁和解锁自动进行,不必担心最后是否释放锁;ReentrantLock也可重入,但加锁和解锁需要手动进行,且次数需一样,否则其他线程无法获得锁。

(3)synchronized不可响应中断,一个线程获取不到锁就一直等着;ReentrantLock可以相应中断。

总结

ReentrantLock是一种可重入的,可实现公平性的互斥锁,它的设计基于AQS框架,可重入和公平性的实现逻辑都不难理解,每重入一次,state就加1,当然在释放的时候,也得一层一层释放。至于公平性,在尝试获取锁的时候多了一个判断:是否有比自己申请早的线程在同步队列中等待,若有,去等待;若没有,才允许去抢占。


相关文章
|
1月前
|
算法 Java 程序员
Java中的Synchronized,你了解多少?
Java中的Synchronized,你了解多少?
|
6月前
|
Java
面试题:java的实现?sythronized和lock的区别
面试题:java的实现?sythronized和lock的区别
47 0
|
6月前
|
Java 编译器
一文带你了解Java中synchronized原理
一文带你了解Java中synchronized原理
56 0
|
存储 Java
一文带你理解Java中Lock的实现原理
当多个线程需要访问某个公共资源的时候,我们知道需要通过加锁来保证资源的访问不会出问题。java提供了两种方式来加锁,一种是关键字:synchronized,一种是concurrent包下的lock锁。
9241 0
|
Java 编译器
Java | 关于synchronized相关理解
Java本身是支持多线程的,而在多线程的情况下,为了防止 多个任务同时访问同一个资源而导致的冲突问题,所以出现了加锁机制。
102 0
Java | 关于synchronized相关理解
|
Java
synchronized【Java】中使用的demo
synchronized【Java】中使用的demo
144 1
synchronized【Java】中使用的demo
|
Java
Java JUC ReentrantLock解析
独占锁 ReentrantLock 原理
90 0
Java JUC ReentrantLock解析
|
Java 调度
Java中的Lock接口
Java中的Lock接口
149 0
|
存储 缓存 算法
Java Lock
本文着重介绍 Java 中 Lock 的不同实现方式。
Java---多线程的加强(1)
Java---多线程的加强(1)
92 0