文章目录
java锁,常用的java锁之间的区别是什么?
synchronized 和 lock 的区别
从功能角度来看,Lock 和Synchronized 都是Java 中用来解决线程安全问题的工具。
从特性来看,
Synchronized 是Java 中的同步关键字,Lock 是J.U.C 包中提供的接口,这个接口有很多实现类,其中就包括ReentrantLock 重入锁
Synchronized 可以通过两种方式来控制锁的粒度,
一种是把synchronized 关键字修饰在方法层面,
另一种是修饰在代码块上,并且我们可以通过Synchronized 加锁对象的声明周期来控制锁的作用范围,比如锁对象是静态对象或者类对象,那么这个锁就是全局锁。
如果锁对象是普通实例对象,那这个锁的范围取决于这个实例的声明周期。
Lock 锁的粒度是通过它里面提供的lock()和unlock()方法决定的,包裹在这两个方法之间的代码, 能够保证线程安全性。而锁的作用域取决于Lock 实例的生命周期。
Lock 比Synchronized 的灵活性更高,Lock 可以自主决定什么时候加锁,什么时候释放锁,只需要调用 lock()和unlock() 这两个方法就行,同时Lock 还提供了非阻塞的竞争锁方法 tryLock()方法,这个方法通过返回 true/false 来告诉当前线程是否已经有其他线程正在使用锁。
Synchronized 由于是关键字,所以它无法实现非阻塞竞争锁的方法,另外,Synchronized 锁的释放是被动的,就是当Synchronized 同步代码块执行完以后或者代码出现异常时才会释放。
Lock 提供了公平锁和非公平锁的机制,公平锁是指线程竞争锁资源时,如果已经有其他线程正在排队等待锁释放,那么当前竞争锁资源的线程无法插队。而非公平锁,就是不管是否有线程在排队等待锁,它都会尝试去竞争一次锁。
Synchronized 只提供了一种非公平锁的实现。
从性能方面来看,Synchronized 和Lock 在性能方面相差不大,在实现上会有一些区别,Synchronized 引入了偏向锁、轻量级锁、重量级锁以及锁升级的方式
来优化加锁的性能,而Lock 中则用到了自旋锁的方式来实现性能优化。
synchronized 和 ReentranLock的区别
ReentranLock分为公平锁和非公平锁,那底层分别是如何实现的呢?
CAS 机制
什么是 AQS ?
AQS 全称是AbstractQueuedSynchronizer, 是juc 下一个核心的抽象类,用于构建各种同步器和锁
比如我们熟悉的 ReentrantLock、ReadWriteLock、CountDownLatch等等是基于AQS.
首先在AQS 里面,有几个核心的组成
● 有volatile修饰的 state 变量: 共享资源的状态
● 以Node节点组成的双端队列——CLH 也是由volatile进行修饰
● 两个维护队列的Node节点head 和 tail
AQS 基本的属性——源码
public abstract class AbstractQueuedSynchronizer
extends AbstractOwnableSynchronizer
implements java.io.Serializable {
//头节点
private transient volatile Node head;
//尾节点
private transient volatile Node tail;
//同步状态
private volatile int state;
static final class Node {
//节点状态
volatile int waitStatus;
//前驱节点
volatile Node prev;
//后继节点
volatile Node next;
//当前节点所代表的线程
volatile Thread thread;
//等待队列使用时的后继节点指针
Node nextWaiter;
}
}