作用:
- synchronized主要用来实现同步,被synchronized修饰 的代码块或方法称为临界区代码,在进入临界区之前,线程会尝试 获取锁,如果锁可用,则线程 会获取锁并进入临界区,执行相应的代码。否则的话线程将被阻塞,直到获取 锁为止;
- ReentrantLock是位于java.util.concurrent.locks包下的一个类,是java中可重入锁的一种实现,可以支持一个 线程对某个资源的重复加锁,底层是基于AQS实现的,在同一个线程加锁时递增,释放锁时递减同步状态的值;
既然 说到了可重入锁,那为啥 需要可重入锁?
可重入锁主要是用来解决线程在 持有锁的情况下 ,再次 请求同一个锁时发生的死锁问题。如果没有可重入 锁,当一个线程已经获取了 锁后,再次请求 该锁会导致 自己要等待自己释放锁,进而产生死锁问题;
具体的场景比如:递归函数中需要获取锁,如果没有可重入锁,线程 在每次递归调用时都会被自己阻塞; 除此之外,还有多个方法可能都需要获取相同的锁 ,没有重入锁的话,他们之间就 不能相互调用。
表格版对比:
自我总结回答表述:(至少答出来 五点 )
两者相同之处在于:两种锁都支持可重入性,synchronized支持隐性的重进入,比如 线程可以在递归执行同步块里的代码而不被阻塞,ReentrantLock需要显式调用lock()方法;
不同之处在于:ReentrantLock比synchronized更加灵活,
(层面)第一个是:因为synchronized是Java中的一个关键词,是JVM层面 的锁,而ReentrantLock是JDK提供的一个类,是API层面的锁 ;
(手动)第二个是:synchronized是自动 加锁与释放锁,而 ReentrantLock需要手动加锁与释放锁 ;
(判锁)第三个是:synchronized不可获取 当前线程是否上锁,而ReentrantLock可以获取当前线程是否上锁,通过isHeldByCurrentThread;
(公平)第四个是:synchronized是非公平锁,ReentrantLock支持获取锁时的公平和非公平性选择,可通过构造 函数new来指定的,默认情况下是false非公平锁;(ReentrantLock lock1 = new ReentrantLock(true))(公平锁会按照线程进来的顺序 一个一个执行)
(中断)第五个是: synchronized不可中断的,也就是一旦给 某一个对象上了锁 ,是不可以中断的,除非出现了异常或代码执行完了, 而ReentrantLock可以手动中断,中断的方式 有两种:
1.设置超时时间tryLock(long timeout,timeUnit unit),尝试获取锁而不阻塞;
2.调用lockInterruptibly()放到代码块中,然后调用interrupt()方法 就可以中断
(锁升级)第六个是 :synchronized底层有锁升级过程(无锁->偏向锁->轻量级锁->(适应性自旋)重量级锁),ReentrantLock没有;
(标识)第七个是:synchronized锁的是对象,锁的信息保存在对象头中,而ReentrantLock是由一个int 类型的state标识来 标识锁的 状态 ;