• 模仿ReentrantLock类自定义锁


    简介

      临近过年了,没什么需求,今天模仿ReentrantLock自定义写了一个自己锁,在这里记录一下,前提是对AQS原理有所了解,分享给大家

    1、自定义锁MyLock

    package com.jacky;
    
    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.locks.AbstractQueuedSynchronizer;
    import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.Lock;
    
    /**
     * Created by jacky on 2018/2/12.
     */
    public class MyLock implements Lock{
        private final Sync sync;
    
        /**
         * 创建公平锁或非公平锁
         * @param fairFlag
         */
        public MyLock(boolean fairFlag){
           sync = fairFlag ? new FairSync() : new NonFairSync();
        }
    
        /**
         * 默认是公平锁
         */
        public MyLock(){
            sync = new FairSync();
        }
    
        /**
         * 获取锁
         */
        @Override
        public void lock() {
             sync.acquire(1);
        }
    
        /**
         * 获取可中断锁
         * @throws InterruptedException
         */
        @Override
        public void lockInterruptibly() throws InterruptedException {
            sync.acquireInterruptibly(1);
        }
    
        /**
         * 它表示用来尝试获取锁,如果获取成功,则返回true,如果获取失败(即锁已被其他线程获取),则返回false,
         * 也就说这个方法无论如何都会立即返回。在拿不到锁时不会一直在那等待
         * @return
         */
        @Override
        public boolean tryLock() {
            return sync.nonfairTryAcquire(1);
        }
    
        /**
         * 获得可超时的锁
         * @param time
         * @param unit
         * @return
         * @throws InterruptedException
         */
        @Override
        public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
            return sync.tryAcquireNanos(1,unit.toNanos(time));
        }
    
        /**
         * 释放锁
         */
        @Override
        public void unlock() {
            sync.release(1);
        }
    
        @Override
        public Condition newCondition() {
            return sync.new ConditionObject();
        }
    
        abstract static class Sync extends AbstractQueuedSynchronizer {
            /**
             * 判断当前线程是否获得锁
             * @return
             */
            @Override
            protected boolean isHeldExclusively() {
                return Thread.currentThread() ==getExclusiveOwnerThread();
            }
    
            /**
             * 尝试释放锁
             * @param arg
             * @return
             */
            @Override
            protected boolean tryRelease(int arg) {
                int newState =getState()-arg;
                setState(newState < 0 ? 0:newState);
                if (newState ==0){
                    setExclusiveOwnerThread(null);
                }
    
                return true;
            }
    
            final boolean nonfairTryAcquire(int arg) {
                Thread thread = Thread.currentThread();
                int state = getState();
                if (state ==0){
                    compareAndSetState(0,state+arg);
                    //设置独占线程
                    setExclusiveOwnerThread(thread);
                    return true;
                }
                if (isHeldExclusively()){
                    setState(state+arg);
                    return true;
                }
                return false;
            }
    
        }
        static class FairSync extends Sync{
            /**
             * 尝试公平锁获得锁
             * @param arg
             * @return
             */
            @Override
            public boolean tryAcquire(int arg) {
                Thread thread = Thread.currentThread();
                int state = getState();
                if (state ==0){
                    //判断队列是否有数据,有数据就返回获取锁失败(公平锁才会这么做)
                    if (hasQueuedPredecessors()){
                        return false;
                    }
                    compareAndSetState(0,state+arg);
                    //设置独占线程
                    setExclusiveOwnerThread(thread);
                    return true;
                }
                if (isHeldExclusively()){
                    setState(state+arg);
                     return true;
                }
                return false;
            }
    
        }
    
        static class NonFairSync extends Sync{
            @Override
            public boolean tryAcquire(int arg) {
                return  nonfairTryAcquire(arg);
            }
        }
    }

    2、测试类

    package com.jacky;
    
    import jdk.internal.org.objectweb.asm.tree.TryCatchBlockNode;
    
    import java.util.concurrent.CountDownLatch;
    import java.util.concurrent.locks.ReentrantLock;
    
    /**
     * Created by jacky on 2018/2/12.
     */
    public class MyLockDemo {
        private final static MyLock lock = new MyLock(false);
        //private final static ReentrantLock lock = new ReentrantLock(true);
        private static int num = 0;
        public static void main(String[] args) {
            int count = 2000;
            CountDownLatch countDownLatch = new CountDownLatch(count);
            Runnable runnable = new Runnable() {
                @Override
                public void run() {
                    try {
                        lock.lock();
                    Thread thread = Thread.currentThread();
                    System.out.println("--start--"+thread.getName());
                    try {
                        Thread.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    num++;
                    System.out.println("--end--");
                    countDownLatch.countDown();
                    }finally {
                       lock.unlock();
                    }
    
                }
            };
            Thread thread = null;
            for (int i = 0; i < count; i++) {
                thread = new Thread(runnable,"t"+i);
                thread.start();
            }
            try {
                countDownLatch.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("--num--"+num);
        }
    }
  • 相关阅读:
    Ubuntu系统下的实用软件推荐
    上传项目到GitHub
    eclipse+fileSyncPlugin+svn+jenkins+tomcat
    js,jq获取元素位置属性及兼容性写法
    清除浮动的几种方法
    sub,dl,dt,排版,横向滚动条,浮动元素居中,box-sizing
    a里面不能嵌套a
    随笔
    自适应屏幕轮播图详解
    tip
  • 原文地址:https://www.cnblogs.com/520playboy/p/8445155.html
Copyright © 2020-2023  润新知