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,当然在释放的时候,也得一层一层释放。至于公平性,在尝试获取锁的时候多了一个判断:是否有比自己申请早的线程在同步队列中等待,若有,去等待;若没有,才允许去抢占。


相关文章
|
4月前
|
Java 编译器
一文带你了解Java中synchronized原理
一文带你了解Java中synchronized原理
36 0
|
存储 缓存 安全
JUC:java.util.concurrent理解与使用示例
阻塞队列(BlockingQueue)是一个支持两个附加操作的队列。这两个附加的操作是:在队列为空时,获取元素的线程会等待队列变为非空。当队列满时,存储元素的线程会等待队列可用。阻塞队列常用于生产者和消费者的场景,生产者是往队列里添加元素的线程,消费者是从队列里拿元素的线程。阻塞队列就是生产者存放元素的容器,而消费者也只从容器里拿元素。
375 0
JUC:java.util.concurrent理解与使用示例
|
Java 编译器
Java | 关于synchronized相关理解
Java本身是支持多线程的,而在多线程的情况下,为了防止 多个任务同时访问同一个资源而导致的冲突问题,所以出现了加锁机制。
79 0
Java | 关于synchronized相关理解
|
存储 Java
【Java】回顾一下Java中的synchronized
synchronized在JDK1.5之前是一个重量级锁,相当于JUC里面的lock锁,但是在1.6版本及之后对它做了很大的升级和优化,它不在那么的笨重了。
40 0
【Java】回顾一下Java中的synchronized
|
Java
Java JUC ReentrantLock解析
独占锁 ReentrantLock 原理
74 0
Java JUC ReentrantLock解析
|
Java API
强哥说Java--Java多线程(三)
强哥说Java--Java多线程(三)
60 0
|
安全 算法 Java
强哥说Java--Java多线程(二)
强哥说Java--Java多线程(二)
105 0
|
Java 调度 双11
强哥说Java--Java多线程(一)
强哥说Java--Java多线程(一)
98 0
强哥说Java--Java多线程(一)
|
Java 调度
Java---多线程的加强(2)
Java---多线程的加强(2)
93 0
Java---多线程的加强(1)
Java---多线程的加强(1)
75 0