• 手写一个简易的ReentrantLock


    public class HqaLock {
        private static final Unsafe unsafe = reflectGetUnsafe();
        private static final long ownerOffset;
    
        /**
         * 锁是否被持有(1)是,(0)否
         */
        AtomicInteger state = new AtomicInteger(0);
        /**
         * 当前持有锁的线程
         */
        volatile Thread owner = new Thread();
        /**
         * 线程等待池
         */
        private Queue<Thread> waitQueue = new LinkedBlockingQueue();
        /**
         * 重入次数
         */
        AtomicInteger reentrantCount = new AtomicInteger(0);
    
        private static Unsafe reflectGetUnsafe() {
            try {
                Field field = Unsafe.class.getDeclaredField("theUnsafe");
                field.setAccessible(true);
                return (Unsafe) field.get(null);
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
        static {
            try {
                ownerOffset = unsafe.objectFieldOffset
                        (HqaLock.class.getDeclaredField("owner"));
            } catch (Exception ex) { throw new Error(ex); }
        }
    
        public void lock(){
            //未被持有则直接获取锁
            if (state.get() == 0){
                //自旋cas改变锁状态
                for(;;){
                    boolean b = state.compareAndSet(0,1);
                    if (b == true){
                        unsafe.compareAndSwapObject(this,ownerOffset,owner,Thread.currentThread());
                        owner = Thread.currentThread();
                        reentrantCount.set(1);
                        break;
                    }
                }
    
            }else {//已经被持有
                //持有锁的线程是是自己
                if (unsafe.getObject(owner,ownerOffset) == Thread.currentThread()){
                    reentrantCount.getAndAdd(1);
                }else {
                    waitQueue.add(Thread.currentThread());
                    //持有锁的线程不是自己
                    while (true){
                        //阻塞休眠
                        LockSupport.park();
                        //如果锁被持有者释放了
                        if (state.get() == 0){
                            owner = Thread.currentThread();
                            state.set(1);
                            break;
                        }
                    }
                }
            }
        }
    
        public void unlock() throws Exception {
    
            if (unsafe.getObject(this,ownerOffset) != Thread.currentThread()){
                throw new Exception("该线程未持有锁");
            }
            //重入次数减1
            reentrantCount.getAndDecrement();
            //直到重入锁全部解开的才能真正的解锁
            if (reentrantCount.get() == 0){
                state.set(0);
                Thread head = waitQueue.peek();
                LockSupport.unpark(head);
            }
    
        }
    }
    

      

  • 相关阅读:
    day32-python阶段性复习六
    golang 项目中坑
    golang crawler
    router
    golang in ubuntu
    go channel 案例分析
    go channel learning
    bee go + mgo
    URL escape and unescape
    [转]good sample of Go
  • 原文地址:https://www.cnblogs.com/huqingan/p/13860264.html
Copyright © 2020-2023  润新知