Java API实现的锁 AbstractQueuedSynchronizer(抽象队列同步器)底层:CAS(CompareAndSet比较并且交换) ReentransLook静态内部类Sync实现AQS,实现公平锁,非公平锁(都是可重入锁) AQS 使用status状态标识该线程是否上锁成功。每重入一次,status+1
ReentransLook上锁
look
public void lock() {
this.sync.acquire(1);
}
public final void acquire(int arg) {
// 尝试上锁,上锁不成功,则放入等到队列
if (!this.tryAcquire(arg) && this.acquireQueued(this.addWaiter(AbstractQueuedSynchronizer.Node.EXCLUSIVE), arg)) {
// 放到等到队列后,当前线程自己中断
selfInterrupt();
}
}
ReentrantsLook非公平锁尝试上锁
protected final boolean tryAcquire(int acquires) {
return this.nonfairTryAcquire(acquires);
}
@ReservedStackAccess
final boolean nonfairTryAcquire(int acquires) {
Thread current = Thread.currentThread();
// 获取当前state状态
int c = this.getState();
// state状态为0,表示没有线程持有锁
if (c == 0) {
// cas设置锁的state状态
if (this.compareAndSetState(0, acquires)) {
// 设置当前持有锁的线程
this.setExclusiveOwnerThread(current);
return true;
}
}
// 判断当前线程是否是持有锁的线程,是则重入,否则加锁失败
else if (current == this.getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0) {
throw new Error("Maximum lock count exceeded");
}
this.setState(nextc);
return true;
}
return false;
}
ReentransLook解锁
public void unlock() {
this.sync.release(1);
}
// aqs部分的代码
public final boolean release(int arg) {
// 尝试解锁成功
if (this.tryRelease(arg)) {
AbstractQueuedSynchronizer.Node h = this.head;
// 阻塞队列头节点不为空,且存在等到锁的线程
if (h != null && h.waitStatus != 0) {
// 唤醒下一个线程
this.unparkSuccessor(h);
}
return true;
}
// 尝试解锁失败
else {
return false;
}
}
@ReservedStackAccess
protected final boolean tryRelease(int releases) {
// states状态 - 1
int c = this.getState() - releases;
// 判断当前线程是否持有锁的线程,否则报异常
if (Thread.currentThread() != this.getExclusiveOwnerThread()) {
throw new IllegalMonitorStateException();
}
// 判断当前线程是否持有锁的线程,是则执行解锁
else {
boolean free = false;
if (c == 0) {
free = true;
this.setExclusiveOwnerThread((Thread)null);
}
this.setState(c);
return free;
}
}
synchronized
idea中 Terminal javap -c xxDemo.class 可以查看class文件反编译为汇编 synchronized 不公平锁,可重入锁 进入锁 monitorenter 退出锁 monitorexit
| 锁状态 | 描述 | 优缺点 | 适用于 |
|---|---|---|---|
| 无锁 | 没有线程在synchronized中时,为无锁状态 | ||
| 偏向锁 | 当只有一个线程进入到同步代码块,没有其他线程竞争时,则为偏向锁,偏向锁标识位设置为1,偏向锁不会自动解锁,只有当下一个线程来的时候,再去判断偏向位,如果是为1,判断持有偏向锁的线程是否活着,是则升级为轻量级锁,否则清楚偏向锁,设置当前线程为持有锁 | ||
| 轻量级锁 | 通过cas竞争获取锁,通过自旋等待 | 响应速度快 | 锁时间短,追求响应速度 |
| 重量级锁 | 响应慢 | 执行锁中的代码所需时间长,响应时间长, | |
| www.jianshu.com/p/11e292d82… |
(这个解释,与AQS中,非公平锁的加锁逻辑一模一样www.cnblogs.com/yuhangwang/…
查看对象头信息--》synchronized在对象头,可查看 blog.csdn.net/qq_42832874… 查看对象头maven依赖
0.16 0.10显示对象头信息格式不同
<!-- https://mvnrepository.com/artifact/org.openjdk.jol/jol-core -->
<dependency>
<groupId>org.openjdk.jol</groupId>
<artifactId>jol-core</artifactId>
<version>0.16</version>
</dependency>
```
<!-- https://mvnrepository.com/artifact/org.openjdk.jol/jol-core -->
<dependency>
<groupId>org.openjdk.jol</groupId>
<artifactId>jol-core</artifactId>
<version>0.10</version>
</dependency>
```
synchronized无锁,偏向锁,轻量级锁,重量级锁 对象头信息查看 blog.csdn.net/zhaocuit/ar…
idea修改虚拟机参数