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);
            }
    
        }
    }
    

      

  • 相关阅读:
    appcan双击返回退出系统
    实现两个矩阵相乘的C语言程序
    编写简单的windows桌面计算器程序
    使用C++实现图形的旋转、缩放、平移
    使用MFC创建C++程序
    SQL server2017的操作(练习题)
    使用SQL语句在SQL server2017上创建数据库
    使用交互式方式在SQL server2017上创建数据库
    解决VS2017编译后的EXE文件不能在其他电脑上运行的问题
    傅里叶分析之掐死教程(完整版)更新于2014.06.06----转载
  • 原文地址:https://www.cnblogs.com/huqingan/p/13860264.html
Copyright © 2011-2022 走看看