zoukankan      html  css  js  c++  java
  • Java限制可以重入次数的锁

    完全 模仿ReentrantLock, 通过继承 java.util.concurrent.locks.Lock , 内置 AbstractQueuedSynchronizer 实现类,限制可以重入次数的锁。

    这个其实不难, 只要稍微注意一点就好了 

    ReenterLimitedLock  关键实现:

    /**
     * l.k
     * 
     * 限制可以重入次数的锁,默认是2次
     * 
     */
    public class ReenterLimitedLock implements Lock, java.io.Serializable {
        private static final long serialVersionUID = 7373984872572414699L;
        private final Sync sync;
    
        /**
         * Creates an instance of {@code ReenterLimitedLock}.
         * This is equivalent to using {@code ReenterLimitedLock(false)}.
         */
        public ReenterLimitedLock() {
            sync = new NonfairSync(2);
        }
    
        public ReenterLimitedLock(int reenterLimit) {
            sync = new NonfairSync(reenterLimit);
        }
    
        public ReenterLimitedLock(boolean fair, int reenterLimit) {
            sync = fair ? new FairSync(reenterLimit) : new NonfairSync(reenterLimit);
        }
    
        public ReenterLimitedLock(boolean fair) {
            sync = fair ? new FairSync(2) : new NonfairSync(2);
        }
    
        abstract static class Sync extends AbstractQueuedSynchronizer {
            private static final long serialVersionUID = -5179523762034025860L;
            private boolean exceeded;
            private int reenterLimit;
    
            public Sync(int reenterLimit) {
                this.reenterLimit = reenterLimit;
            }
    
            abstract void lock();
    
            final boolean nonfairTryAcquire(int acquires) throws MaximumLockCountExceededException {
                final Thread current = Thread.currentThread();
                int c = getState();
                if (c == 0) {
                    if (compareAndSetState(0, acquires)) {
                        setExclusiveOwnerThread(current);
                        return true;
                    }
                }
                else if (current == getExclusiveOwnerThread()) {
                    int nextc = c + acquires;
    //                if (nextc < 0) // overflow
                    if (nextc > reenterLimit) { // 关键 
                        exceeded = true;
    //                    return false;
    //                    throw new IllegalStateException("Maximum lock count exceeded" + 2);
                        throw new MaximumLockCountExceededException(reenterLimit);
                    }
                    setState(nextc);
                    return true;
                }
                return false;
            }
    
            protected final boolean tryRelease(int releases) {
                if (isExceeded()) {
                    return false;
                }
                int c = getState() - releases;
                if (Thread.currentThread() != getExclusiveOwnerThread())
                    throw new IllegalMonitorStateException();
                boolean free = false;
                if (c == 0) {
                    free = true;
                    setExclusiveOwnerThread(null);
                }
                setState(c);
                return free;
            }
    
            protected final boolean isHeldExclusively() {
                // While we must in general read state before owner,
                // we don't need to do so to check if current thread is owner
                return getExclusiveOwnerThread() == Thread.currentThread();
            }
    
            final ConditionObject newCondition() {
                return new ConditionObject();
            }
    
            // Methods relayed from outer class
    
            final Thread getOwner() {
                return getState() == 0 ? null : getExclusiveOwnerThread();
            }
    
            final int getHoldCount() {
                return isHeldExclusively() ? getState() : 0;
            }
    
            final boolean isLocked() {
                return getState() != 0;
            }
    
            /**
             * Reconstitutes the instance from a stream (that is, deserializes it).
             */
            private void readObject(java.io.ObjectInputStream s)
                throws java.io.IOException, ClassNotFoundException {
                s.defaultReadObject();
                setState(0); // reset to unlocked state
            }
    
            public boolean isExceeded() {
                return exceeded;
            }
    
            public void setExceeded(boolean exceeded) {
                this.exceeded = exceeded;
            }
    
            public int getReenterLimit() {
                return reenterLimit;
            }
    
            public void setReenterLimit(int reenterLimit) {
                this.reenterLimit = reenterLimit;
            }
    
        }
    
        /**
         * Sync object for non-fair locks
         */
        static final class NonfairSync extends Sync {
            private static final long serialVersionUID = 7316153563782823691L;
    
            public NonfairSync(int reenterLimit) {
                super(reenterLimit);
            }
    
            /**
             * Performs lock.  Try immediate barge, backing up to normal
             * acquire on failure.
             */
            final void lock() {
                if (compareAndSetState(0, 1))
                    setExclusiveOwnerThread(Thread.currentThread());
                else
                    acquire(1);
            }
    
            protected final boolean tryAcquire(int acquires) {
                return nonfairTryAcquire(acquires);
            }
        }
    
        /**
         * Sync object for fair locks
         */
        static final class FairSync extends Sync {
            private static final long serialVersionUID = -3000897897090466540L;
    
            public FairSync(int reenterLimit) {
                super(reenterLimit);
            }
    
            final void lock() {
                acquire(1);
            }
    
            /**
             * Fair version of tryAcquire.  Don't grant access unless
             * recursive call or no waiters or is first.
             */
            protected final boolean tryAcquire(int acquires) {
                final Thread current = Thread.currentThread();
                int c = getState();
                if (c == 0) {
                    if (!hasQueuedPredecessors() &&
                        compareAndSetState(0, acquires)) {
                        setExclusiveOwnerThread(current);
                        return true;
                    }
                }
                else if (current == getExclusiveOwnerThread()) {
                    int nextc = c + acquires;
    //                if (nextc < 0)
                    if (nextc > getReenterLimit())  //  这里是关键
                        throw new MaximumLockCountExceededException(getReenterLimit());
    //                    throw new Error("Maximum lock count exceeded");
                    setState(nextc);
                    return true;
                }
                return false;
            }
        }
    
        public void lock() {
            sync.lock();
        }
     
        public void lockInterruptibly() throws InterruptedException {
            sync.acquireInterruptibly(1);
        }
     
        public boolean tryLock() {
            return sync.nonfairTryAcquire(1);
        }
     
        public boolean tryLock(long timeout, TimeUnit unit)
                throws InterruptedException {
            return sync.tryAcquireNanos(1, unit.toNanos(timeout));
        }
    
        public void unlock() {
            sync.release(1);
        }
    
        public Condition newCondition() {
            return sync.newCondition();
        }
    
        public int getHoldCount() {
            return sync.getHoldCount();
        }
    
        public boolean isHeldByCurrentThread() {
            return sync.isHeldExclusively();
        }
    
        public boolean isLocked() {
            return sync.isLocked();
        }
    
        public final boolean isFair() {
            return sync instanceof FairSync;
        }
    
        protected Thread getOwner() {
            return sync.getOwner();
        }
    
        public final boolean hasQueuedThreads() {
            return sync.hasQueuedThreads();
        }
    
        public final boolean hasQueuedThread(Thread thread) {
            return sync.isQueued(thread);
        }
    
        public final int getQueueLength() {
            return sync.getQueueLength();
        }
    
        protected Collection<Thread> getQueuedThreads() {
            return sync.getQueuedThreads();
        }
    
        public boolean hasWaiters(Condition condition) {
            if (condition == null)
                throw new NullPointerException();
            if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
                throw new IllegalArgumentException("not owner");
            return sync.hasWaiters((AbstractQueuedSynchronizer.ConditionObject)condition);
        }
    
        public int getWaitQueueLength(Condition condition) {
            if (condition == null)
                throw new NullPointerException();
            if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
                throw new IllegalArgumentException("not owner");
            return sync.getWaitQueueLength((AbstractQueuedSynchronizer.ConditionObject)condition);
        }
    
        protected Collection<Thread> getWaitingThreads(Condition condition) {
            if (condition == null)
                throw new NullPointerException();
            if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
                throw new IllegalArgumentException("not owner");
            return sync.getWaitingThreads((AbstractQueuedSynchronizer.ConditionObject)condition);
        }
    
        public String toString() {
            Thread o = sync.getOwner();
            return super.toString() + ((o == null) ?
                                       "[Unlocked]" :
                                       "[Locked by thread " + o.getName() + "]");
        }
    }

    MaximumLockCountExceededException 异常:

    public class MaximumLockCountExceededException extends IllegalStateException {
    //public class MaximumLockCountExceededException extends Exception {
        public MaximumLockCountExceededException(String s) {
            super(s);
        }
        public MaximumLockCountExceededException(int n) {
            super("Maximum lock count exceeded: " + n);
        }
    }

    测试:

    /**
     * Created by L.k on 2018/11/29.
     */
    public class Testaa {
    
        ReenterLimitedLock twiceLock = new ReenterLimitedLock();
        
        public static void main(String[] args) {
            ReenterLimitedLock twiceLock = new ReenterLimitedLock();
            Testaa testaa =  new Testaa(twiceLock);
            testaa.aa("asf");
        }
    
        public Testaa(ReenterLimitedLock twiceLock) {
            this.twiceLock = twiceLock;
        }
    
    
        public void aa(String aa) {
            try {
                twiceLock.lock();
                Thread.sleep(1000);
                System.out.println("aa = [" + aa + "]");
                bb(aa);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                twiceLock.unlock();
            }
        }
    
        public void bb(String bb) {
            try {
                twiceLock.lock();
                Thread.sleep(1000);
    
                System.out.println("bb = [" + bb + "]");
    
                cc(bb);
    
                System.out.println("Testaa.bb");
    
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                twiceLock.unlock();
            }
        }
    
        public void cc(String cc) {
            try {
                twiceLock.lock();
                Thread.sleep(1000);
    
                System.out.println("cc = [" + cc + "]");
    
            } catch (InterruptedException e) {
                e.printStackTrace();
    //        } catch (InterruptedException | IllegalStateException e) {
            } catch (MaximumLockCountExceededException e) { // 这里必须要 捕获 MaximumLockCountExceededException, 否则 bb 方法也会异常退出
    //            e.printStackTrace();
                System.out.println("xxxx IllegalStateException = " + e);
            } finally {
                twiceLock.unlock();
            }
        }
    }
  • 相关阅读:
    Java(二)
    JS === 关于getElementsByClassName()
    JS === 简易放大镜
    JS === 拖拽盒子
    JS === 实现多个光标跟随事件
    JS === 实现回到顶部
    JS === 实现通过点击td 跳转相应的图片
    final、static关键字
    java面向对象——构造方法
    java面向对象——多态
  • 原文地址:https://www.cnblogs.com/FlyAway2013/p/10038313.html
Copyright © 2011-2022 走看看