Lock锁底层原理实现

底层基于AQS+Cas+LockSupport 锁实现

Synchronized与Lock锁之间的区别

Lock基于AQS封装的锁结合CAS实现,而Lock锁的升级过程需要自己实现;

Synchronized是基于C++虚拟机封装,JDK1.6优化可以实现锁的升级过程;

LockSupport的用法

AbstractQueuedsynchronizer(AQS)

  • Fairsync ---公平锁
  • Nonfairsync-非公平锁
  • 父类都是AbstractQueuedsynchronizer

ReentrantLock默认情况下都是非公平锁

公平锁/非公平锁原理在此不做介绍

AQS实现原理

状态:0,1 5,7>1 当前线程重入+1

状态:0===当前我们锁没有被任何线程持有状态:

0===1锁已经被其他线程持有

有一个没有获取到锁的线程集合(双向链表实现)。

Node结点采用双向链表的形式存放正在等待的线程waitStatus 状态、thread等到锁的线程

  • CANCELLED值为-1,表示当前的线程被取消
  • SIGNAL 释放资源后需唤醒后续节点
  • CONDITION,值为-2,等待condition唤醒;
  • PROPAGATE
  1. 值为-3,工作于共享锁状态,需要向后传播,比如根据资源是否剩余,唤醒后继节点;
  2. 值为0,表示当前节点在sync队列中,等待着获取锁。
  • Head 头结点等待队列的头结点
  • Tail尾结点正在等待的线程
  • State锁的状态0无锁、1已经获取锁,当前线程重入不断+1
  • exclusiveOwnerThread 记录锁的持有

Cas+LockSupport+AQS手写Lock锁

package com.example.test.study;

import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.LockSupport;

/**
 * @author Wcy
 * @Date 2022/10/6 20:19
 */
public class MyLock {
    /**
     * 0表示未锁定,1表示锁定
     */
    private AtomicInteger lockState = new AtomicInteger(0);
    /**
     * 获取到锁的线程
     */
    private Thread lockCurrentThread = null;
    /**
     * 等待队列
     */
    private ConcurrentLinkedDeque<Thread> waiters = new ConcurrentLinkedDeque<>();

    /**
     * 获取锁
     */
    public void lock() {
        acquire();
    }

    public boolean acquire() {
        while(true) {
            if (lockState.compareAndSet(0, 1)) {
                lockCurrentThread = Thread.currentThread();
                //获取锁成功
                return true;
            }
            //获取锁失败
            waiters.add(Thread.currentThread());
            //阻塞当前线程
            LockSupport.park();
        }
    }

    public boolean compareAndSet(int expect, int update) {
        return lockState.compareAndSet(0, 1);
    }

    /**
     * 释放锁
     */
    public boolean unlock() {
        if (lockCurrentThread == null) {
            return false;
        }
        if (lockCurrentThread == Thread.currentThread()) {
            boolean res= compareAndSet(1, 0);
            if(res){
                //公平锁唤醒 链表第一个
                Thread first = waiters.getFirst();
                if (first != null) {
                    LockSupport.unpark(first);
                }

                //非公平锁唤醒 全部唤醒
                //waiters.forEach(t -> {
                //    LockSupport.unpark(t);
                //});
                return true;
            }
        }
        return false;
    }

}

Semaphore信号量底层原理

本质基于AQS做封装

CountDownLatch原理

CountDownLatch源码分析

CountDownLatch是一种java.util.concurrent包下一个同步工具类,它允许一个或多个线程等待直到在其他线程中一组操作执行完成。和join方法非常类似

CountDownLatch 底层是基于AQS实现的

CountDownLatch countDownLatch=new CountDownLatch(2)AQS的state状态为2

调用countDownLatch.countDown();方法的时候状态-1当AQS状态state为0的情况下,则唤醒正在等待的线程。

最后修改:2022 年 10 月 06 日
如果觉得我的文章对你有用,请随意赞赏