zoukankan      html  css  js  c++  java
  • 手写一个简易的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);
            }
    
        }
    }
    

      

  • 相关阅读:
    Java Native Method
    SQL语句优化
    Ibatis的环境搭建以及遇到的问题解决
    Java 构建器
    SpringMVC自定义视图 Excel视图和PDF视图
    java 枚举的常见使用方法
    mysql 根据某些字段之和排序
    MFC The Screen Flickers When The Image Zoomed
    How To Debug Qmake Pro File
    Gcc And MakeFile Level1
  • 原文地址:https://www.cnblogs.com/huqingan/p/13860264.html
Copyright © 2011-2022 走看看