• 使用Unsafe来实现自定义锁


    1.使用Unsafe类

    import sun.misc.Unsafe;
    
    class UnsafePackage {
        private static Unsafe unsafe;
    
        static {
            try {
                Class<Unsafe> unsafeClass = Unsafe.class;
                Field theUnsafe = unsafeClass.getDeclaredField("theUnsafe");
                theUnsafe.setAccessible(true);
                unsafe = (Unsafe) theUnsafe.get(null);
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    
        public static Unsafe getUnsafe() {
            return unsafe;
        }
    }

    2.声明简单锁

    class CustomLock {
        private volatile int status;
    
        private static Unsafe unsafe = UnsafePackage.getUnsafe();
        private static long statusOffset;
        private WaitingQueue queue = new WaitingQueue();
    
        static {
            try {
                statusOffset = unsafe.objectFieldOffset(CustomLock.class.getDeclaredField("status"));
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    
        private boolean comareAndSetStatus(int originalStatus, int updateStatus) {
            return unsafe.compareAndSwapInt(this, statusOffset, originalStatus, updateStatus);
        }
    
        public boolean lock() {
            if (comareAndSetStatus(0, 1)) {
                //System.out.println("竞争锁成功!继续执行后面的代码");
                return true;
            }
    
            //System.out.println("竞争锁失败!进入等待队列");
            push(Thread.currentThread());
            while (!comareAndSetStatus(0, 1)) {
                UnsafePackage.getUnsafe().park(false, 0);
            }
            return true;
        }
    
        public boolean unlock() {
            status = 0;
            Thread thread = pop();
            if (thread != null) {
                UnsafePackage.getUnsafe().unpark(thread);
            }
            return true;
        }
    
        private void push(Thread thread) {
            queue.push(thread);
        }
    
        private Thread pop() {
            return queue.pop();
    
        }
    }

    3.竞争锁失败的进队列

    class WaitingQueue {
        private volatile int status;
        private static long statusOffset;
    
        /**
         * 非线程安全,使用时,也要加锁
         */
        private LinkedList<Thread> queue = new LinkedList<>();
    
        static {
            try {
                statusOffset = UnsafePackage.getUnsafe().objectFieldOffset(WaitingQueue.class.getDeclaredField("status"));
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    
        public void push(Thread thread) {
            while (!comareAndSetStatus(0, 1)) {
    
            }
            queue.offerLast(thread);
            comareAndSetStatus(1, 0);
            return;
        }
    
        public Thread pop() {
            while (!comareAndSetStatus(0, 1)) {
    
            }
            Thread elem = null;
            if (!queue.isEmpty()) {
                elem = queue.pop();
            }
            comareAndSetStatus(1, 0);
            return elem;
        }
    
        private boolean comareAndSetStatus(int originalStatus, int updateStatus) {
            return UnsafePackage.getUnsafe().compareAndSwapInt(this, statusOffset, originalStatus, updateStatus);
        }
    }

    3.调用如下

    public class CustomLockTest {
    
    
        private static int count = 0;
    
        public static void main(String[] args) throws InterruptedException {
            int threadCount = 1500;
            CountDownLatch countDownLatch = new CountDownLatch(threadCount);
            CustomLock lock = new CustomLock();
            long start = System.currentTimeMillis();
            IntStream.range(0, threadCount)
                    .forEach(p -> {
                        new Thread() {
                            @Override
                            public void run() {
                                lock.lock();
                                try {
                                    for (int i = 0; i < 1000; i++) {
                                        count++;
                                    }
                                    countDownLatch.countDown();
                                } finally {
                                    lock.unlock();
                                }
                            }
                        }.start();
                    });
    
            countDownLatch.await();
            long end = System.currentTimeMillis();
            System.out.println("结果值为:" + count + ",共花费了" + (end - start) + "毫秒!");
        }
    }
    结果值为:1500000,共花费了601毫秒!
  • 相关阅读:
    安装node-gyp
    node版本切换
    electron-vue运行只出现项目目录不出现效果
    高级运维工程师的必备技术
    linux 下的shutdown指令
    数据库实体联系模型与关系模型
    数据库表设计1
    实体-关系模型
    Excel中怎么快速选中区域
    EXCEL中给包含某个字段的单元格所在行标注颜色
  • 原文地址:https://www.cnblogs.com/zhshlimi/p/10919652.html
Copyright © 2020-2023  润新知