reentrantreadwritelock.java

来自「SRI international 发布的OAA框架软件」· Java 代码 · 共 1,180 行 · 第 1/4 页

JAVA
1,180
字号
                return readerLock_;
            else if (waitingWriters_ > 0)
                return writerLock_;
            else
                return null;
        }
    }

    /**
     * Reader and Writer requests are maintained in two different
     * wait sets, by two different objects. These objects do not
     * know whether the wait sets need notification since they
     * don't know preference rules. So, each supports a
     * method that can be selected by main controlling object
     * to perform the notifications.  This base class simplifies mechanics.
     */

    static interface Signaller { // base for ReaderLock and WriterLock
        void signalWaiters();
    }

    class ReaderLock implements Signaller, Lock, java.io.Serializable {

        /**
         * Acquires the read lock.
         *
         * <p>Acquires the read lock if the write lock is not held by
         * another thread and returns immediately.
         *
         * <p>If the write lock is held by another thread then
         * the current thread becomes disabled for thread scheduling
         * purposes and lies dormant until the read lock has been acquired.
         */
        public void lock() {
            boolean wasInterrupted = false;
            while (true) {
                try {
                    lockInterruptibly();
                    if (wasInterrupted) {
                        Thread.currentThread().interrupt();
                    }
                    return;
                }
                catch (InterruptedException e) {
                    wasInterrupted = true;
                }
            }
        }

        /**
         * Acquires the read lock unless the current thread is
         * {@link Thread#interrupt interrupted}.
         *
         * <p>Acquires the read lock if the write lock is not held
         * by another thread and returns immediately.
         *
         * <p>If the write lock is held by another thread then the
         * current thread becomes disabled for thread scheduling
         * purposes and lies dormant until one of two things happens:
         *
         * <ul>
         *
         * <li>The read lock is acquired by the current thread; or
         *
         * <li>Some other thread {@link Thread#interrupt interrupts}
         * the current thread.
         *
         * </ul>
         *
         * <p>If the current thread:
         *
         * <ul>
         *
         * <li>has its interrupted status set on entry to this method; or
         *
         * <li>is {@link Thread#interrupt interrupted} while acquiring
         * the read lock,
         *
         * </ul>
         *
         * then {@link InterruptedException} is thrown and the current
         * thread's interrupted status is cleared.
         *
         * <p>In this implementation, as this method is an explicit
         * interruption point, preference is given to responding to
         * the interrupt over normal or reentrant acquisition of the
         * lock.
         *
         * @throws InterruptedException if the current thread is interrupted
         */
        public void lockInterruptibly() throws InterruptedException {
            if (Thread.interrupted())
                throw new InterruptedException();
            InterruptedException ie = null;
            synchronized (this) {
                if (!startReadFromNewReader()) {
                    for (; ; ) {
                        try {
                            ReaderLock.this.wait();
                            if (startReadFromWaitingReader())
                                return;
                        }
                        catch (InterruptedException ex) {
                            cancelledWaitingReader();
                            ie = ex;
                            break;
                        }
                    }
                }
            }
            if (ie != null) {
                // fall through outside synch on interrupt.
                // This notification is not really needed here,
                //   but may be in plausible subclasses
                writerLock_.signalWaiters();
                throw ie;
            }
        }

        /**
         * Attempts to release this lock.
         *
         * <p> If the number of readers is now zero then the lock
         * is made available for write lock attempts.
         */
        public void unlock() {
            Signaller s = endRead();
            if (s != null)
                s.signalWaiters();
        }

        public synchronized void signalWaiters() {
            ReaderLock.this.notifyAll();
        }

        /**
         * Acquires the read lock only if the write lock is not held by
         * another thread at the time of invocation.
         *
         * <p>Acquires the read lock if the write lock is not held by
         * another thread and returns immediately with the value
         * <tt>true</tt>. Even when this lock has been set to use a
         * fair ordering policy, a call to <tt>tryLock()</tt>
         * <em>will</em> immediately acquire the read lock if it is
         * available, whether or not other threads are currently
         * waiting for the read lock.  This &quot;barging&quot; behavior
         * can be useful in certain circumstances, even though it
         * breaks fairness. If you want to honor the fairness setting
         * for this lock, then use {@link #tryLock(long, TimeUnit)
         * tryLock(0, TimeUnit.SECONDS) } which is almost equivalent
         * (it also detects interruption).
         *
         * <p>If the write lock is held by another thread then
         * this method will return immediately with the value
         * <tt>false</tt>.
         *
         * @return <tt>true</tt> if the read lock was acquired.
         */
        public boolean tryLock() {
            return startRead();
        }

        /**
         * Acquires the read lock if the write lock is not held by
         * another thread within the given waiting time and the
         * current thread has not been {@link Thread#interrupt
         * interrupted}.
         *
         * <p>Acquires the read lock if the write lock is not held by
         * another thread and returns immediately with the value
         * <tt>true</tt>. If this lock has been set to use a fair
         * ordering policy then an available lock <em>will not</em> be
         * acquired if any other threads are waiting for the
         * lock. This is in contrast to the {@link #tryLock()}
         * method. If you want a timed <tt>tryLock</tt> that does
         * permit barging on a fair lock then combine the timed and
         * un-timed forms together:
         *
         * <pre>if (lock.tryLock() || lock.tryLock(timeout, unit) ) { ... }
         * </pre>
         *
         * <p>If the write lock is held by another thread then the
         * current thread becomes disabled for thread scheduling
         * purposes and lies dormant until one of three things happens:
         *
         * <ul>
         *
         * <li>The read lock is acquired by the current thread; or
         *
         * <li>Some other thread {@link Thread#interrupt interrupts} the current
         * thread; or
         *
         * <li>The specified waiting time elapses
         *
         * </ul>
         *
         * <p>If the read lock is acquired then the value <tt>true</tt> is
         * returned.
         *
         * <p>If the current thread:
         *
         * <ul>
         *
         * <li>has its interrupted status set on entry to this method; or
         *
         * <li>is {@link Thread#interrupt interrupted} while acquiring
         * the read lock,
         *
         * </ul> then {@link InterruptedException} is thrown and the
         * current thread's interrupted status is cleared.
         *
         * <p>If the specified waiting time elapses then the value
         * <tt>false</tt> is returned.  If the time is less than or
         * equal to zero, the method will not wait at all.
         *
         * <p>In this implementation, as this method is an explicit
         * interruption point, preference is given to responding to
         * the interrupt over normal or reentrant acquisition of the
         * lock, and over reporting the elapse of the waiting time.
         *
         * @param timeout the time to wait for the read lock
         * @param unit the time unit of the timeout argument
         *
         * @return <tt>true</tt> if the read lock was acquired.
         *
         * @throws InterruptedException if the current thread is interrupted
         * @throws NullPointerException if unit is null
         *
         */
        public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
            if (Thread.interrupted()) throw new InterruptedException();
            InterruptedException ie = null;
            long nanos = unit.toNanos(timeout);
            synchronized (this) {
                if (nanos <= 0)
                    return startRead();
                else if (startReadFromNewReader())
                    return true;
                else {
                    long deadline = Utils.nanoTime() + nanos;
                    for (; ; ) {
                        try {
                            TimeUnit.NANOSECONDS.timedWait(ReaderLock.this, nanos);
                        }
                        catch (InterruptedException ex) {
                            cancelledWaitingReader();
                            ie = ex;
                            break;
                        }
                        if (startReadFromWaitingReader())
                            return true;
                        else {
                            nanos = deadline - Utils.nanoTime();
                            if (nanos <= 0) {
                                cancelledWaitingReader();
                                break;
                            }
                        }
                    }
                }
            }
            // safeguard on interrupt or timeout:
            writerLock_.signalWaiters();
            if (ie != null)
                throw ie;
            else
                return false; // timed out
        }

        /**
         * Throws <tt>UnsupportedOperationException</tt> because
         * <tt>ReadLocks</tt> do not support conditions.
         * @throws UnsupportedOperationException always
         */
        public Condition newCondition() {
            throw new UnsupportedOperationException();
        }

        /**
         * Returns a string identifying this lock, as well as its lock state.
         * The state, in brackets, includes the String
         * &quot;Read locks =&quot; followed by the number of held
         * read locks.
         * @return a string identifying this lock, as well as its lock state.
         */
        public String toString() {
            int r = getReadLockCount();
            return super.toString() +
                "[Read locks = " + r + "]";
        }

    }

    class WriterLock implements Signaller, Lock, java.io.Serializable,
                                CondVar.LockInfo {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?