简单独占锁实现

学习AQS、ReentrantLock和CountDownLatch有感,根据原理写了一个简单的独占锁的demo。


首先是极简AQS(AbstractQueuedSynchronizer)类

AbstractQueuedSimpleSynchronizer

package com.sephy.test.abstractlock;

import java.util.concurrent.locks.AbstractQueuedSynchronizer;

/**
 * @version V1.0
 * @功能描述:
 * @名称: com.sephy.test.abstractlock.AbstractQuenedSimpleSync
 * @作者 Sephy
 * @创建时间 2021-10-01 14:50
 */
public abstract class AbstractQueuedSimpleSynchronizer {
    //锁状态 0-free 1-locked
    private volatile int state;
    private Thread owner;

    protected final int getState() {
        return state;
    }
    protected final void setState(int newState) {
        state = newState;
    }
    protected final boolean compareAndSetState(int expect, int update){
        if(getState() == expect){
            //当前state大于更新后的state,说明要释放锁
                        if(expect > update){
                            System.out.println(Thread.currentThread().getName()+"释放锁成功!!!");
                        }
                        //当前state小于更新后的state,说明要加锁
                        else if(expect < update){
                            System.out.println(Thread.currentThread().getName()+"加锁成功!!!");
                        }
            setState(update);
            return true;
        }else return false;
    }
    protected Thread getExclusiveOwnerThread(){
        return owner;
    }

    /**
     * 获取独占锁
     * @param arg
     * @throws InterruptedException
     */
    public final void acquireExclusive(int arg)
            throws InterruptedException {
        if (Thread.interrupted())
            throw new InterruptedException();
        if (tryAcquireExclusive(arg) < 0) {
            //无锁,可加锁
            doAcquireExclusive(arg);
        } else{
            System.out.println(Thread.currentThread().getName()+"加锁失败~~~锁已经被"+owner.getName()+"占用");
        }

    }
    //加锁
    private void doAcquireExclusive(int arg) {
        if(compareAndSetState(0,1)){
            owner = Thread.currentThread();
            System.out.println(Thread.currentThread().getName()+"加锁成功!!!");
        }else{
            System.out.println(Thread.currentThread().getName()+"加锁失败~~~"+owner.getName()+"占用");
        }
    }
    //获取独占锁,子类实现
    abstract int tryAcquireExclusive(int arg);


    /**
     * 释放独占锁
     * @param arg
     * @return
     */
    public final boolean releaseExclusive(int arg) {
        if (owner == Thread.currentThread()) {
            if(tryReleaseExclusive(arg)){
                doReleaseExclusive(arg);
                return true;
            }else{
                System.out.println(Thread.currentThread().getName()+"释放锁失败~~~当前无锁");
                return false;
            }
        } else{
            System.out.println(Thread.currentThread().getName()+"释放锁失败~~~当前不是锁的使用者"+owner.getName());
            return false;
        }

    }
    public void doReleaseExclusive(int arg) {
//        System.out.println(Thread.currentThread().getName()+"释放锁成功!!!");
    }
    //释放独占锁,子类实现
    abstract boolean tryReleaseExclusive(int arg);



}


根据CountDownLatch的思想,实现简单的Lock

MyLock

package com.sephy.test.abstractlock;

/**
 * @version V1.0
 * @功能描述:
 * @名称: com.sephy.test.abstractlock.MyLock
 * @作者 Sephy
 * @创建时间 2021-10-01 15:15
 */
public class MyLock {

    private static final class Sync extends AbstractQueuedSimpleSynchronizer {
        private static boolean wait = false;
        Sync(int state,boolean wait){
            this.wait = wait;
            setState(state);
        }
        //1:free -1:locked
        @Override
        int tryAcquireExclusive(int arg) {
            if(wait){
                //等待锁的释放
                for(;;){
                    if(getState() == 0){
                        return -1;
                    }
                }
            }else{
                //只请求一次,锁被占用则返回
                return (getState() == 0) ? -1 : 1;
            }


        }

        @Override
        boolean tryReleaseExclusive(int arg) {
            int c = getState();
            if (c == 0)
                return false;
            int nextc = c-1;
            if (compareAndSetState(c, nextc))
                return nextc == 0;
            return false;
        }
    }

    private final Sync sync;
    public MyLock(int count,boolean wait){
        if (count < 0) throw new IllegalArgumentException("count < 0");
        this.sync = new Sync(count,wait);
    }

    public void acquireLock() throws InterruptedException {
        sync.acquireExclusive(1);
    }
    public void releaseLock() {
        sync.releaseExclusive(1);
    }


}


测试类

MyLockTest

package com.sephy.test.abstractlock;
import lombok.SneakyThrows;
/**
 * @version V1.0
 * @功能描述:
 * @名称: com.sephy.test.abstractlock.MyLockTest
 * @作者 Sephy
 * @创建时间 2021-10-01 15:36
 */
public class MyLockTest {
    public static void main(String[] args) {
        MyLock lock = new MyLock(0,true);
        Thread t1 = new Thread(new Runnable() {
            @SneakyThrows
            @Override
            public void run() {
                lock.acquireLock();
                Thread.sleep(4000L);
                lock.releaseLock();
                Thread.sleep(1000L);
                lock.releaseLock();
                Thread.sleep(3000L);
                lock.acquireLock();
                Thread.sleep(3000L);
                lock.releaseLock();
            }
        });
        Thread t2 = new Thread(new Runnable() {
            @SneakyThrows
            @Override
            public void run() {
                Thread.sleep(1000L);
                lock.acquireLock();
                Thread.sleep(2000L);
                lock.releaseLock();
                Thread.sleep(4000L);
                lock.acquireLock();
                Thread.sleep(2000L);
                lock.releaseLock();
            }
        });
        t1.start();
        t2.start();
    }
}

当wait=true时,结果

Thread-0加锁成功!!!
Thread-0释放锁成功!!!
Thread-1加锁成功!!!
Thread-0释放锁失败~~~当前不是锁的使用者Thread-1
Thread-1释放锁成功!!!
Thread-0加锁成功!!!
Thread-0释放锁成功!!!
Thread-1加锁成功!!!
Thread-1释放锁成功!!!

当wait=false时,结果

Thread-0加锁成功!!!
Thread-1加锁失败~~~锁已经被Thread-0占用
Thread-1释放锁失败~~~当前不是锁的使用者Thread-0
Thread-0释放锁成功!!!
Thread-0释放锁失败~~~当前无锁
Thread-1加锁成功!!!
Thread-0加锁失败~~~锁已经被Thread-1占用
Thread-1释放锁成功!!!
Thread-0释放锁失败~~~当前不是锁的使用者Thread-1


{context}