1、自定义锁代码

/*
	核心:
		1) 自定义可重入锁的类,实现 Lock 接口;
		2) 重写 Lock 接口中所有的方法;
		3) 自定义一个 私有内部类,并继承 AbstractQueuedSynchronizer;
		4) 重写 tryAcquire 和 tryRelease 方法,以及新增一个获取 Condition 对象的方法。
		
	自定义同步器在实现时只需要实现共享资源state的获取与释放方式即可,
    至于具体线程等待队列的维护(如获取资源失败入队/唤醒出队等),AQS已经在顶层实现好了
    
    下方代码主要参考 ReentrantLock 的实现,所以推荐了解一下 ReentrantLock。
*/


package com.example.aqs;

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 MyLock implements Lock {

    // 信号量
    private final Integer semaphore = 1;

    // 期望值
    private final Integer expectValue = 0;

    // 初始化自定义锁
    private final Helper myLock = new Helper();

    // 自定义 私有内部类
    private class Helper extends AbstractQueuedSynchronizer {

        @Override
        protected boolean tryAcquire(int semaphore) {
            int state = getState();
            // 等于0代表当前没有线程获取锁
            if (state == 0) {
                // 使用CAS方式同步修改状态state
                if (compareAndSetState(expectValue, semaphore)) {
                    setExclusiveOwnerThread(Thread.currentThread());
                    // true: 成功获取对象锁
                    return true;
                }
                return false;
            }
            // 如果有线程已经占用了锁
            // 判断占用当前锁的线程是否为现在的线程
            if (Thread.currentThread().equals(getExclusiveOwnerThread())) {
                setState(getState() + semaphore);
                return true;
            }
            return false;
        }

        @Override
        protected boolean tryRelease(int semaphore) {
            int state = getState() - semaphore;
            if (state == 0) {
                // Exclusive: 独占的
                setExclusiveOwnerThread(null);
                setState(state);
                // 当前对象处于完全释放状态时,返回true;
                // true: 如果此对象现在处于完全释放状态,那么任何等待的线程都可能尝试获取; false: 其他
                return true;
            }
            setState(state);
            // 当前对象处于未完全释放状态时,返回false;
            return false;
        }

        public Condition newConditionObject() {
            return new ConditionObject();
        }
    }

    @Override
    public void lock() {
        myLock.acquire(semaphore);
    }

    @Override
    public void lockInterruptibly() throws InterruptedException {
        myLock.acquireInterruptibly(semaphore);
    }

    @Override
    public boolean tryLock() {
        return myLock.tryAcquire(semaphore);
    }

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

    @Override
    public void unlock() {
        myLock.release(semaphore);
    }

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


2、测试是否能保证数据的一致性

package com.example.aqs;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 测试自定义锁
 */
public class MyLockTest {

    private Integer m = 0;
	
    // 自定义的锁对象
    private MyLock myLock = new MyLock();

    // JUC下的锁对象
    // private Lock lock = new ReentrantLock();

    private void increment() {
        myLock.lock();
        System.out.println(++m);
        myLock.unlock();
    }

    public static void main(String[] args) {
        MyLockTest myLockTest = new MyLockTest();
        for (int i = 0; i < 100; i++) {
            new Thread(myLockTest::increment).start();
        }
    }

}

/*
	结果:
		1
		2
		3
		......
		100
*/


3、测试可重入性

package com.example.aqs;

import java.util.concurrent.locks.Lock;

public class MyLockReentrantTest {

    private final MyLock myLock = new MyLock();

    private void method1() {
        myLock.lock();
        System.out.println("Nice to meet to you, I'm method1!");
        method2();
        myLock.unlock();
    }

    private void method2() {
        myLock.lock();
        System.out.println("Nice to meet to you, too! I'm method2!");
        myLock.unlock();
    }

    public static void main(String[] args) {
        MyLockReentrantTest myLockReentrantTest = new MyLockReentrantTest();
        new Thread(myLockReentrantTest::method1).start();
    }
}


/*
	结果:
        Nice to meet to you, I'm method1!
        Nice to meet to you, too! I'm method2!
*/