手写简单的Lock

本文介绍了手写Lock的三种方式,从基础的Lock接口实现开始,逐步进阶到可重入锁,并最终通过AQS(AbstractQueuedSynchronizer)来实现锁机制,以此加深对Java并发编程的理解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

昨天的面试,让我知道了阅读源码的重要性,今天就手写三种简单Lock来进行JUC的巩固。

代码实现

1、简单的Lock

package com.coolstar.locks;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

public class MyLock1 implements Lock {
    private boolean isLock = false;
    @Override
    public synchronized void lock() {
        while(isLock) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        isLock = true;
    }

    @Override
    public void lockInterruptibly() throws InterruptedException {

    }

    @Override
    public boolean tryLock() {
        return false;
    }

    @Override
    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
        return false;
    }

    @Override
    public synchronized void unlock() {
        isLock = false;
        notify();
    }

    @Override
    public Condition newCondition() {
        return null;
    }
}

对Lock接口进行实现,并且简单实现它的Lock和unLock方法。

2、可重入锁Lock

package com.coolstar.locks;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

public class MyLock2 implements Lock {
    private boolean isLock =false;
    private Thread lockBy = null;
    private int lockCount = 0;
    @Override
    public synchronized void lock() {
        Thread currentThread = Thread.currentThread();
        while (isLock && lockBy != currentThread) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        isLock = true;
        lockBy = currentThread;
        lockCount++;
    }

    @Override
    public void lockInterruptibly() throws InterruptedException {

    }

    @Override
    public boolean tryLock() {
        return false;
    }

    @Override
    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
        return false;
    }

    @Override
    public synchronized void unlock() {
        isLock = false;
        if (lockBy == Thread.currentThread()) {
            lockCount--;
            if (lockCount == 0) {
                notify();
                isLock = false;
                lockBy = null;
            }
        }

    }

    @Override
    public Condition newCondition() {
        return null;
    }
}

我们在第一种的基础上增加了可重入锁的机制。当获取锁的线程是当前线程时,进行可重入,lockCount自增。

3、基于AQS的Lock

package com.coolstar.locks;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

public class MyLock3 implements Lock {


    private class Helper extends AbstractQueuedSynchronizer {
        //1.获取状态

        //2.拿到状态,CAS判断(双重检测),并设置为独占锁

        //3.判断是不是当前线程,要是当前线程的话就可重入
        @Override
        protected boolean tryAcquire(int arg) {

            Thread t = Thread.currentThread();
            int state = getState();
            //说明无锁,就进行CAS进行取,若成功就设置为独占锁
            if (state == 0) {
                if (compareAndSetState(0,arg)) {
                    setExclusiveOwnerThread(Thread.currentThread());
                    return true;
                }
                //如果当前线程已经拿到锁,那就state+1进行重入
            }else if (t == getExclusiveOwnerThread()) {
                setState(state+1);
                return true;
            }
            return false;
        }
        //1.先看是不是当前线程,如果不是,就不能释放,抛出异常

        //2.如果是的话,判断state,如果state-1(arg) = 0,那就释放

        @Override
        protected boolean tryRelease(int arg) {
            //锁的获取和释放需要一一对应,那么调用这个方法的线程,一定是当前线程
            if (Thread.currentThread() != getExclusiveOwnerThread()) {
                throw new RuntimeException();
            }
            int state = getState() - arg;
            setState(state);
            //如果state为0,说明独占锁被取消了
            if(state == 0) {
                setExclusiveOwnerThread(null);
                return true;
            }
            return false;
        }

        //ConditionObject不能在外部使用,是AQS里面的
        public Condition newCondition() {

            return new ConditionObject();
        }
    }

    Helper helper = new Helper();

    @Override
    public void lock() {
        helper.acquire(1);
    }

    @Override
    public void lockInterruptibly() throws InterruptedException {

    }

    @Override
    public boolean tryLock() {
        return helper.tryAcquire(1);
    }

    @Override
    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
        return helper.tryAcquireNanos(1,unit.toNanos(time));
    }

    @Override
    public void unlock() {
        helper.release(1);
    }

    @Override
    public Condition newCondition() {
        return helper.newCondition();
    }
}

我们定义一个内部类实现AQS接口,再通过AQS实现锁。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值