手写一个ReentrantLock,包括AQS

继承AQS

public class ReentrantLockUseAQS extends AbstractQueuedSynchronizer {

    @Override
    protected boolean tryAcquire(int arg) {
        if (compareAndSetState(0,1)) {
            setExclusiveOwnerThread(Thread.currentThread());
            return true;
        }
        return false;
    }


    @Override
    protected boolean tryRelease(int arg) {
        if (compareAndSetState(1,0)) {
            setExclusiveOwnerThread(null);
            return true;
        }
        return false;
    }

    public static void main(String[] args) {
        final ReentrantLockUseAQS lock = new ReentrantLockUseAQS();

        new Thread(() -> {
            // 获取锁
            lock.acquire(1);
            System.out.println("T1成功获取锁," + LocalDateTime.now());
            try {
                TimeUnit.SECONDS.sleep(3);
                System.out.println("T1执行完毕");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }finally {
                // 释放锁
                lock.release(1);
                System.out.println("T1释放了锁," + LocalDateTime.now());
            }
        },"T1").start();

        new Thread(() -> {
            try {
                // 让T1先获取锁
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            lock.acquire(1);
            System.out.println("T2获取到锁," + LocalDateTime.now());
            lock.release(1);
        },"T2").start();
    }
}

用自己实现的AQS

  1. acquire思路:需要获取锁的线程不断去轮询获取锁,多次获取不到则放入到队尾且park,等待其他线程唤醒,被唤醒后继续去获取锁,若获取到则继续往下执行
  2. release思路:释放自己持有的锁,唤醒下一个线程节点去争抢锁
  3. 如何保证线程安全:使用Java自带的Unsafe的CAS控制
/**
 * 模仿AQS写的锁
 * 底层主要是LockSupport进行park跟unpark
 * 使用Unsafe的CAS保证修改变量的原子性
 */
public class MyLock {
    private volatile int state;
    private static final Unsafe unsafe;
    private static final long stateOffset;
    protected transient Thread exclusiveOwnerThread;
    static {
        try {
            Field f = Unsafe.class.getDeclaredField("theUnsafe");
            f.setAccessible(true);
            unsafe = (Unsafe) f.get(null);

            stateOffset = unsafe.objectFieldOffset
                    (MyLock.class.getDeclaredField("state"));

        } catch (Exception ex) { throw new Error(ex); }
    }
    protected transient volatile Node head;

    protected transient volatile Node tail;

    class Node {

        Node prev;

        Node next;

        Thread thread;

        Node() {
        }

        Node(Thread thread) {
            this.thread = thread;// Used by addWaiter
        }
    }



    protected final boolean compareAndSetState(int expect, int update) {
        return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
    }

    public void acquire() {
        if (!tryAcquire()) {
            Node node = new Node(Thread.currentThread());
            addWaiter(node);
            acquireQueued(node);
        }
    }

    /**
     * 如果当前node具备竞争锁的条件,那么循环获取锁
     * 否则park
     */
    protected final boolean acquireQueued(Node node) {
        for (;;) {
        	/**
        	 * 此处跟源码不同的是源码判断尝试获取锁的条件是当前node是head的next
        	 * 而我的就head才能尝试获取锁
        	 */
            if (node == head && tryAcquire()) {
                if (head.next == null) {
                    head = tail = null;
                } else {
                    head = head.next;
                }
                break;
            } else {
                System.out.println(Thread.currentThread().getName() + ",park");
                LockSupport.park();
            }
        }
        return true;
    }

    public void release() {
        if (exclusiveOwnerThread != Thread.currentThread()) {
            throw new RuntimeException("当前线程没有占有锁,无法释放锁");
        }
        if (compareAndSetState(1,0)) {
            exclusiveOwnerThread = null;
        }

        if (head != null) {
            System.out.println("释放锁时,UnPark线程:" + head.thread.getName());
            LockSupport.unpark(head.thread);
        }
    }

    protected boolean tryAcquire() {
        final Thread current = Thread.currentThread();
        if (state == 0) {
            if (compareAndSetState(0, 1)) {
                exclusiveOwnerThread = current;
                return true;
            }
        }
        return false;
    }



    /**
     * 将元素添加到同步队列中
     */
    protected Node addWaiter(Node node) {

        if (tail != null) {
            tail.next = node;
            node.prev = tail;
            tail = node;
        } else {
            head = tail = node;
        }
        System.out.println(Thread.currentThread().getName() + "进入同步队列");
        return node;
    }



    public static void main(String[] args) {
        final MyLock myLock = new MyLock();
        Runnable task1 = () -> {
            myLock.acquire();
            System.out.println(Thread.currentThread().getName() + "获取了锁," + LocalDateTime.now());
            try {
                TimeUnit.SECONDS.sleep(4);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            myLock.release();
        };

        Runnable task2 = () -> {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            myLock.acquire();
            System.out.println(Thread.currentThread().getName() + "获取了锁," + LocalDateTime.now());

            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            myLock.release();
        };

        Runnable task3 = () -> {
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            myLock.acquire();
            System.out.println(Thread.currentThread().getName() + "获取了锁," + LocalDateTime.now());
            myLock.release();
        };



        new Thread(task1,"T1").start();
        new Thread(task2,"T2").start();
        new Thread(task3,"T3").start();
    }
}

await、signal

public class MyCondition extends MyLock{
    /** First node of condition queue. */
    private transient Node firstWaiter;
    /** Last node of condition queue. */
    private transient Node lastWaiter;
    /**
     * 判断当前是否持有锁,若持有则:
     * 1.放弃当前获取的锁
     * 2.放入等待队列
     * 3.park
     */
    public void await() throws InterruptedException {
        final Thread currentThread = Thread.currentThread();
        if (exclusiveOwnerThread != currentThread) {
            throw new RuntimeException("当前线程没持有锁");
        }

        final Node node = new Node(currentThread);

        if (compareAndSetState(1,0)) {
            exclusiveOwnerThread = null;
            addConditionWaiter(node);
            LockSupport.unpark(head.thread);
            LockSupport.park();
            System.out.println(Thread.currentThread().getName() + "被UNPark,重新acquire");
            /**
             * 被UnPark后继续去争抢锁
             */
            acquireQueued(node);
        }
    }

    /**
     * 1.将等待队列的Node线程放到同步队列
     * 2.唤醒同步队列头结点线程去争锁
     */
    public void signal() {
        addWaiter(firstWaiter);
        LockSupport.unpark(firstWaiter.thread);
    }

    private Node addConditionWaiter(Node node) {

        if (lastWaiter != null) {
            lastWaiter.next = node;
            node.prev = lastWaiter;
            lastWaiter = node;
        } else {
            firstWaiter = lastWaiter = node;
        }
        System.out.println(Thread.currentThread().getName() + ",addConditionWaiter");
        return node;
    }

    public static void main(String[] args) {
        MyCondition myLock = new MyCondition();

        new Thread(() -> {
            myLock.acquire();
            System.out.println("T1获取了锁" + LocalDateTime.now());
            try {
                System.out.println("T1 await让出了锁" + LocalDateTime.now());
                myLock.await();
                System.out.println("T1 await结束被signal" + LocalDateTime.now());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            myLock.release();
            System.out.println("T1释放了锁");
        },"T1").start();

        new Thread(() -> {
            myLock.acquire();
            System.out.println("T2获取了锁" + LocalDateTime.now());
            myLock.signal();
            System.out.println("T2 signal其他线程");
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("T2休眠三秒后再释放锁");
            myLock.release();
        },"T2").start();
    }

}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值