使用AQS自定义重入锁
一、创建MyLock
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 Helper helper = new Helper(); @Override public void lock() { helper.acquire(1); } @Override public void lockInterruptibly() throws InterruptedException { helper.acquireInterruptibly(1); } @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(); } private class Helper extends AbstractQueuedSynchronizer { @Override protected boolean tryAcquire(int arg) { //如果第一个线程进来,可以拿到锁,返回true //如果第二个线程进来,拿不到锁,返回false,有种特例,如果当前进来的线程和当前保存的线程是同一个线程,则可以拿到锁,但是要更新状态值 //如何判断是第一个线程进来还是其他线程进来 int state = getState(); Thread t = Thread.currentThread(); if (state == 0) {//判断是否是第一个线程 if (compareAndSetState(0, arg)) { setExclusiveOwnerThread(Thread.currentThread()); return true; } } else if(getExclusiveOwnerThread() == t) {//判断当前进来的线程和当前保存的线程是否是同一个线程,实现重入锁,因为锁的是对象,所以只要是同一个Helper对象线程就是同一个线程 setState(state + 1); return true; } return false; } @Override protected boolean tryRelease(int arg) { //锁的获取和释放肯是一一对应的,那么调用此方法的线程一定是当前线程 if (Thread.currentThread() != getExclusiveOwnerThread()) { throw new RuntimeException(); } int state = getState() - arg; setState(state); if (state == 0) { setExclusiveOwnerThread(null); return true; } return false; } protected ConditionObject newCondition() { return new ConditionObject(); } } }
二、编写测试代码
public class TestMyLock { private int value; private MyLock myLock = new MyLock(); public int getValue() { myLock.lock(); try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } value ++; myLock.unlock(); return value; } public void a() { myLock.lock(); System.out.println("a"); b(); myLock.unlock(); } public void b() { myLock.lock(); System.out.println("b"); myLock.unlock(); } public static void main(String[] args) { TestMyLock testMyLock = new TestMyLock(); //检测是否会并发 Runnable runnable = () -> { for (int i = 0; i<100; i++) { System.out.println(Thread.currentThread().getId()+",值:" + testMyLock.getValue()); } }; new Thread(runnable).start(); new Thread(runnable).start(); new Thread(runnable).start(); //检测重入锁 Runnable runnable1 = () -> testMyLock.a(); new Thread(runnable1).start(); } }