锁-AbstractQueuedSynchronizer,ReentrantsLook源码

91 阅读1分钟

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…

image.png (这个解释,与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修改虚拟机参数

image.png