ReentrantLock和synchronized的区别

概述

Synchronized

优点:实现简单,语义清晰,便于JVM堆栈跟踪,加锁解锁过程由JVM自动控制,提供了多种优化方案,使用更广泛

缺点:悲观的排他锁,不能进行高级功能

Lock

优点:可定时的、可轮询的与可中断的锁获取操作,提供了读写锁、公平锁和非公平锁  

缺点:需手动释放锁unlock,不适合JVM进行堆栈跟踪

相同点

都是可重复锁

ReentrantLock用于替代synchronized 但是ReentrantLock比较灵活

https://www.cnblogs.com/jiangds/p/6476293.html

应用层面

相比synchronized,ReentrantLock增加了一些高级功能主要有以下三个:等待可中断、可实现公平锁、以及锁可以绑定多个条件

1)使用reentrantlock可以进行“尝试锁定”tryLock,这样无法锁定,或者在指定时间内无法锁定,线程可以决定是否继续等待

      返回值是Boolean类型 表示在指定时间内 是否拿到锁

    void m2() {
        
        boolean locked = false;
        
        try {
            locked = lock.tryLock(5, TimeUnit.SECONDS);
            System.out.println("m2 ..." + locked);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            if(locked) lock.unlock();
        }
        
    }

2)等待可中断

使用ReentrantLock还可以调用lockInterruptibly方法,可以对线程interrupt方法做出响应,
在一个线程等待锁的过程中,可以被打断

Lock lock = new ReentrantLock();       
        
        Thread t1 = new Thread(()->{
            try {
                lock.lock();
                System.out.println("t1 start");
                TimeUnit.SECONDS.sleep(Integer.MAX_VALUE);
                System.out.println("t1 end");
            } catch (InterruptedException e) {
                System.out.println("interrupted!");
            } finally {
                lock.unlock();
            }
        });
        t1.start();
        
        Thread t2 = new Thread(()->{
            try {
                //lock.lock();
                lock.lockInterruptibly(); //可以对interrupt()方法做出响应
                System.out.println("t2 start");
                TimeUnit.SECONDS.sleep(5);
                System.out.println("t2 end");
            } catch (InterruptedException e) {
                System.out.println("interrupted!");
            } finally {
                lock.unlock();
            }
        });
        t2.start();
        
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        t2.interrupt(); //打断线程2的等待

3)可实现公平锁

 非公平锁是线程直接抢锁。公平锁会检查等待队列里有没有在等待的线程,如果有它会排在等待队列后面等待

public class ReentrantLock5 extends Thread {

    private static ReentrantLock lock=new ReentrantLock(true); //参数为true表示为公平锁,请对比输出结果
    public void run() {
        for(int i=0; i<100; i++) {
            lock.lock();
            try{
                System.out.println(Thread.currentThread().getName()+"获得锁");
            }finally{
                lock.unlock();
            }
        }
    }
    public static void main(String[] args) {
        ReentrantLock5 rl=new ReentrantLock5();
        Thread th1=new Thread(rl);
        Thread th2=new Thread(rl);
        th1.start();
        th2.start();
    }
}

Thread-1获得锁
Thread-2获得锁
Thread-1获得锁
Thread-2获得锁
Thread-1获得锁......

4)绑定多个条件

参考Lock Condition实现生产者和消费者

https://www.cnblogs.com/ssskkk/p/12659224.html#_label0

实现原理不同

https://www.cnblogs.com/ssskkk/p/12814323.html

 

posted @ 2020-04-08 11:48  palapala  阅读(1080)  评论(0编辑  收藏  举报