并发编程之ReadWriteLock读写锁

1、前言
ReadWriteLock是jdk5中提供得读写分离锁。读写分离锁可以有效地帮助减少锁竞争,以提高系统性能。
在实际应用中,如果读操作次数远大于写操作,则读写锁就可以发挥最大得功效,提升系统性能。

- 读读不互斥:读读之间不阻塞
- 读写互斥:读阻写,写也会阻读
- 写写互斥:写写阻塞

2、使用��
package package3;

import java.util.Random;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * 读读(非阻塞)、读写(阻塞)、写写(阻塞)
 *
 * 以下demo,不用读写锁,要花费20秒。 使用读写锁,远小于花费20秒
 */
public class ReadWriteLockDemo {
    private static Lock lock = new ReentrantLock();
    private static ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();//实例化读写锁
    private static Lock readLock = readWriteLock.readLock();//获取读锁
    private static Lock writeLock = readWriteLock.writeLock();//获取写锁

    private int value;

    public int handleRead(Lock lock){
        try{
            lock.lock();//模拟读操作
            Thread.sleep(1000);//模拟耗时
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();

        }
        return this.value;
    }

    public void handleWrite(Lock lock,int index){
        try{
            lock.lock();
            Thread.sleep(1000);
            this.value = index;
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        final ReadWriteLockDemo readWriteLockDemo = new ReadWriteLockDemo();

        //读线程
        Runnable readRunable = new Runnable() {
            @Override
            public void run() {
                readWriteLockDemo.handleRead(readLock);
               // readWriteLockDemo.handleRead(lock);
            }
        };

        //写线程
        Runnable writeRunable = new Runnable() {
            @Override
            public void run() {
                readWriteLockDemo.handleWrite(writeLock,new Random().nextInt(1000));
                //readWriteLockDemo.handleWrite(lock,new Random().nextInt(1000));
            }
        };

        for (int i=0;i<18;i++){
            new Thread(readRunable).start();
        }

        for (int i=18;i<20;i++){
            new Thread(writeRunable).start();
        }
    }
}

由于采用读写锁,读读之间并行,节省了大量实际。整个程序大约2秒运行完成。如果不采用读写锁,程序执行将长达20秒。

3、Java并发-ReentrantReadWriteLock源码分析
4、ReentrantReadWriteLock源码

package java.util.concurrent.locks;
import java.util.concurrent.TimeUnit;
import java.util.Collection;


public class ReentrantReadWriteLock
        implements ReadWriteLock, java.io.Serializable {
    private static final long serialVersionUID = -6992448646407690164L;
    /** 内部类读锁 */
    private final ReentrantReadWriteLock.ReadLock readerLock;
    /** 内部类写锁 */
    private final ReentrantReadWriteLock.WriteLock writerLock;
    /** 同步机制类 */
    final Sync sync;

    /**
     *构造函数,默认不公平锁
     */
    public ReentrantReadWriteLock() {
        this(false);
    }

    /**
     * 构造函数
     * @param fair 是否公平锁  true:公平  false不公平
     */
    public ReentrantReadWriteLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();//实例化同步锁(公平或不公平)
        readerLock = new ReadLock(this);//实例化读锁
        writerLock = new WriteLock(this);//实例化些锁
    }

    //获取写锁
    public ReentrantReadWriteLock.WriteLock writeLock() { return writerLock; }
    //获取读锁
    public ReentrantReadWriteLock.ReadLock  readLock()  { return readerLock; }

    /**
     * reentrantreadwritelock同步的实现。
     * 定义为公平和不公平两版本。
     */
    abstract static class Sync extends AbstractQueuedSynchronizer {
        private static final long serialVersionUID = 6317671515068378041L;

        /*
         * 读写锁中最重要的就是Sync类,它继承自AQS。AQS使用一个int型来保存状态,状态在这里就代表锁,它提供了获取和修改状态的方法。
         * 状态的高16位用作读锁(共享锁方式),低16位用作写锁(独占锁方式)
         */

        //最多支持65535个写锁和65535个读锁;低16位表示写锁计数,高16位表示持有读锁的线程数
        static final int SHARED_SHIFT   = 16;
        //由于读锁用高位部分,读锁个数加1,其实是状态值加 2^16
        static final int SHARED_UNIT    = (1 << SHARED_SHIFT);
        static final int MAX_COUNT      = (1 << SHARED_SHIFT) - 1;
        /**写锁的掩码,用于状态的低16位有效值 */
        static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;

        /** 读锁(共享锁)计数,当前持有读锁的线程数,c的高16位 */
        static int sharedCount(int c)    { return c >>> SHARED_SHIFT; }
        /** 写锁(独占锁)的计数,也就是它的重入次数,c的低16位*/
        static int exclusiveCount(int c) { return c & EXCLUSIVE_MASK; }

        /**
         * 每个线程持有读锁的计数
         */
        static final class HoldCounter {
            int count = 0;
            //使用id而不是引用是为了避免保留垃圾。注意这是个常量。
            final long tid = getThreadId(Thread.currentThread());
        }

        /**
         * 采用继承是为了重写 initialValue 方法,这样就不用进行这样的处理:
         * 如果ThreadLocal没有当前线程的计数,则new一个,再放进ThreadLocal里。
         * 可以直接调用 get。
         * */
        static final class ThreadLocalHoldCounter
                extends ThreadLocal {
            public HoldCounter initialValue() {
                return new HoldCounter();
            }
        }

        /**
         * 当前线程持有的可重入读锁的数量,仅在构造方法和readObject(反序列化)
         * 时被初始化,当持有锁的数量为0时,移除此对象。
         */
        private transient ThreadLocalHoldCounter readHolds;

        /**
         * 最近一个成功获取读锁的线程的计数。这省却了ThreadLocal查找,
         * 通常情况下,下一个释放线程是最后一个获取线程。这不是 volatile 的,
         * 因为它仅用于试探的,线程进行缓存也是可以的
         * (因为判断是否是当前线程是通过线程id来比较的)。
         */
        private transient HoldCounter cachedHoldCounter;


        /**firstReader是第一个获得读锁的线程;
         * firstReaderHoldCount是firstReader的重入计数;
         * 更准确的说,firstReader是最后一个把共享计数从0改为1,并且还没有释放锁。
         * 如果没有这样的线程,firstReader为null;
         * firstReader不会导致垃圾堆积,因为在tryReleaseShared中将它置空了,除非
         * 线程异常终止,没有释放读锁。
         *
         * 跟踪无竞争的读锁计数时,代价很低
         */
        private transient Thread firstReader = null;
        private transient int firstReaderHoldCount;

        Sync() {
            readHolds = new ThreadLocalHoldCounter();
            setState(getState()); // ensures visibility of readHolds
        }

        /**
         * 读锁是否需要阻塞
         */
        abstract boolean readerShouldBlock();

        /**
         * 写锁是否需要阻塞
         */
        abstract boolean writerShouldBlock();

        /**
         * 释放写锁
         */
        protected final boolean tryRelease(int releases) {
            if (!isHeldExclusively())//当前线程没有持有锁,抛异常
                throw new IllegalMonitorStateException();
            //获得一次锁,同步状态+1,释放时每释放一次同步状态-1,直到状态为0,可重入锁全部释放完毕。
            int nextc = getState() - releases;
            boolean free = exclusiveCount(nextc) == 0;
            if (free)//如果锁是可用的
                setExclusiveOwnerThread(null);//当前线程释放锁
            setState(nextc);// 重入计数
            return free;
        }

        //获取锁
        protected final boolean tryAcquire(int acquires) {

            Thread current = Thread.currentThread();//获取当前线程
            int c = getState();//获取锁同步状态
            int w = exclusiveCount(c);//获取写锁(独占锁)的计数
            if (c != 0) {//说明存在锁,可能是读锁,也可能是写锁
                // (Note: if c != 0 and w == 0 then shared count != 0)
                if (w == 0 || current != getExclusiveOwnerThread())//当前锁没有被占用或者当前获得锁得线程不是当前线程
                    return false;
                if (w + exclusiveCount(acquires) > MAX_COUNT) //线程溢出
                    throw new Error("Maximum lock count exceeded");

                //执行到这里,说明存在写锁,且由当前线程持有
                // 重入计数
                setState(c + acquires);
                return true;
            }

            //执行到这里,说明不存在任何锁
            //WriterShouldBlock留给子类实现公平策略
            //使用CAS修改状态
            if (writerShouldBlock() ||
                    !compareAndSetState(c, c + acquires))
                return false;
            setExclusiveOwnerThread(current);
            return true;
        }

        /**
         * 释放读锁
         */
        protected final boolean tryReleaseShared(int unused) {
            Thread current = Thread.currentThread();//获取当前线程
            /**
             * 当前线程是第一个获取到锁的,如果此线程要释放锁了,则firstReader置空
             * 否则,将线程持有的锁计数减1
             */
            if (firstReader == current) {
                // assert firstReaderHoldCount > 0;
                if (firstReaderHoldCount == 1)
                    firstReader = null;
                else
                    firstReaderHoldCount--;
            } else {
                HoldCounter rh = cachedHoldCounter;
                //如果cachedHoldCounter为空,或者不等于当前线程
                if (rh == null || rh.tid != getThreadId(current))
                    rh = readHolds.get();
                int count = rh.count;
                if (count <= 1) {
                    readHolds.remove();
                    if (count <= 0)
                        throw unmatchedUnlockException();
                }
                --rh.count;
            }
            //有可能其他线程也在释放读锁,所以要确保释放成功
            for (;;) {
                int c = getState();
                int nextc = c - SHARED_UNIT;
                if (compareAndSetState(c, nextc))
                    // 释放读锁对其他读线程没有任何影响,
                    // 但可以允许等待的写线程继续,如果读锁、写锁都空闲。
                    return nextc == 0;
            }
        }

        private IllegalMonitorStateException unmatchedUnlockException() {
            return new IllegalMonitorStateException(
                    "attempt to unlock read lock, not locked by current thread");
        }

        //Sync中的tryAcquireShared  尝试获取读锁
        protected final int tryAcquireShared(int unused) {
            /*
            (1)如果当前写锁被其他线程持有,则获取读锁失败;
            (2)写锁空闲,或者写锁被当前线程持有(写锁可降级为读锁),在公平策略下,它可能需要阻塞,那么tryAcquireShared()就可能失败,则需要进入队列等待;
                如果是非公平策略,会尝试获取锁,使用CAS修改状态,修改成功,则获得读锁,否则也会进入同步队列等待;
            (3)进入同步队列后,就是由AQS来完成唤醒。
            */
            Thread current = Thread.currentThread();//获取当前线程
            int c = getState();//同步获取状态
            /*** 持有写锁的线程可以获得读锁 **/
            if (exclusiveCount(c) != 0 &&            //写锁被占用
                    getExclusiveOwnerThread() != current) //且不是由当前线程持有
                return -1;

            /******** 执行到这里表明:写锁可用,或者写锁由当前线程持有   *****/
            //获得读锁的数量
            int r = sharedCount(c);
            /** 如果读锁没有阻塞,且没有溢出,则使用CAS修改状态,并且修改成功 */
            if (!readerShouldBlock() &&
                    r < MAX_COUNT &&
                    compareAndSetState(c, c + SHARED_UNIT)) {//修改高16位的状态,所以要加上2^16
                //这是第一个占有读锁的线程,所以设置firstReader
                if (r == 0) {
                    firstReader = current;
                    firstReaderHoldCount = 1;
                } else if (firstReader == current) {
                    firstReaderHoldCount++;//重入计数加1
                } else {
                    // 非 firstReader 读锁重入计数更新
                    //将cachedHoldCounter设置为当前线程
                    HoldCounter rh = cachedHoldCounter;
                    if (rh == null || rh.tid != getThreadId(current))
                        cachedHoldCounter = rh = readHolds.get();
                    else if (rh.count == 0)
                        readHolds.set(rh);
                    rh.count++;
                }
                return 1;
            }
            //获取读锁失败,放到循环里重试
            return fullTryAcquireShared(current);
        }

        /**
         * 处理读写失败的完整读取版本
         * 和tryacquireshared不同在于,此方法循环获取锁
         */
        final int fullTryAcquireShared(Thread current) {
            HoldCounter rh = null;
            for (;;) {
                int c = getState();//同步获取状态
                if (exclusiveCount(c) != 0) { //写锁被占用
                    if (getExclusiveOwnerThread() != current)//不是由当前线程持有
                        return -1;
                    // else we hold the exclusive lock; blocking here
                    // would cause deadlock.
                } else if (readerShouldBlock()) {//读锁没有阻塞
                    // Make sure we're not acquiring read lock reentrantly
                    if (firstReader == current) {//当前线程是第一个占有读锁的线程
                        // assert firstReaderHoldCount > 0;
                    } else {//当前线程不是第一个占有读锁的线程
                        if (rh == null) {
                            //将cachedHoldCounter设置为当前线程
                            rh = cachedHoldCounter;
                            if (rh == null || rh.tid != getThreadId(current)) {
                                rh = readHolds.get();
                                if (rh.count == 0)
                                    readHolds.remove();
                            }
                        }
                        if (rh.count == 0)
                            return -1;
                    }
                }
                if (sharedCount(c) == MAX_COUNT) //线程个数溢出,抛出溢出
                    throw new Error("Maximum lock count exceeded");
                if (compareAndSetState(c, c + SHARED_UNIT)) {//修改高16位的状态,所以要加上2^16
                    //这是第一个占有读锁的线程,所以设置firstReader
                    if (sharedCount(c) == 0) {
                        firstReader = current;
                        firstReaderHoldCount = 1;
                    } else if (firstReader == current) {//重入计数加1
                        firstReaderHoldCount++;
                    } else {
                        // 非 firstReader 读锁重入计数更新
                        //将cachedHoldCounter设置为当前线程
                        if (rh == null)
                            rh = cachedHoldCounter;
                        if (rh == null || rh.tid != getThreadId(current))
                            rh = readHolds.get();
                        else if (rh.count == 0)
                            readHolds.set(rh);
                        rh.count++;
                        cachedHoldCounter = rh; // cache for release
                    }
                    return 1;
                }
            }
        }

        /**
         * Performs tryLock for write, enabling barging in both modes.
         * This is identical in effect to tryAcquire except for lack
         * of calls to writerShouldBlock.
         */
        final boolean tryWriteLock() {
            Thread current = Thread.currentThread();
            int c = getState();
            if (c != 0) {
                int w = exclusiveCount(c);
                if (w == 0 || current != getExclusiveOwnerThread())
                    return false;
                if (w == MAX_COUNT)
                    throw new Error("Maximum lock count exceeded");
            }
            if (!compareAndSetState(c, c + 1))
                return false;
            setExclusiveOwnerThread(current);
            return true;
        }

        /**
         * Performs tryLock for read, enabling barging in both modes.
         * This is identical in effect to tryAcquireShared except for
         * lack of calls to readerShouldBlock.
         */
        final boolean tryReadLock() {
            Thread current = Thread.currentThread();
            for (;;) {
                int c = getState();
                if (exclusiveCount(c) != 0 &&
                        getExclusiveOwnerThread() != current)
                    return false;
                int r = sharedCount(c);
                if (r == MAX_COUNT)
                    throw new Error("Maximum lock count exceeded");
                if (compareAndSetState(c, c + SHARED_UNIT)) {
                    if (r == 0) {
                        firstReader = current;
                        firstReaderHoldCount = 1;
                    } else if (firstReader == current) {
                        firstReaderHoldCount++;
                    } else {
                        HoldCounter rh = cachedHoldCounter;
                        if (rh == null || rh.tid != getThreadId(current))
                            cachedHoldCounter = rh = readHolds.get();
                        else if (rh.count == 0)
                            readHolds.set(rh);
                        rh.count++;
                    }
                    return true;
                }
            }
        }

        /**
         * 判断当前线程是否持有锁
         */
        protected final boolean isHeldExclusively() {
            return getExclusiveOwnerThread() == Thread.currentThread();
        }

        // Methods relayed to outer class

        final ConditionObject newCondition() {
            return new ConditionObject();
        }

        final Thread getOwner() {
            // Must read state before owner to ensure memory consistency
            return ((exclusiveCount(getState()) == 0) ?
                    null :
                    getExclusiveOwnerThread());
        }

        final int getReadLockCount() {
            return sharedCount(getState());
        }

        final boolean isWriteLocked() {
            return exclusiveCount(getState()) != 0;
        }

        final int getWriteHoldCount() {
            return isHeldExclusively() ? exclusiveCount(getState()) : 0;
        }

        final int getReadHoldCount() {
            if (getReadLockCount() == 0)
                return 0;

            Thread current = Thread.currentThread();
            if (firstReader == current)
                return firstReaderHoldCount;

            HoldCounter rh = cachedHoldCounter;
            if (rh != null && rh.tid == getThreadId(current))
                return rh.count;

            int count = readHolds.get().count;
            if (count == 0) readHolds.remove();
            return count;
        }

        /**
         * Reconstitutes the instance from a stream (that is, deserializes it).
         */
        private void readObject(java.io.ObjectInputStream s)
                throws java.io.IOException, ClassNotFoundException {
            s.defaultReadObject();
            readHolds = new ThreadLocalHoldCounter();
            setState(0); // reset to unlocked state
        }

        final int getCount() { return getState(); }
    }

    /**
     * 非公平同步锁
     */
    static final class NonfairSync extends Sync {
        private static final long serialVersionUID = -8159625535654395037L;
        final boolean writerShouldBlock() {
            return false; // writers can always barge
        }
        final boolean readerShouldBlock() {
            /* As a heuristic to avoid indefinite writer starvation,
             * block if the thread that momentarily appears to be head
             * of queue, if one exists, is a waiting writer.  This is
             * only a probabilistic effect since a new reader will not
             * block if there is a waiting writer behind other enabled
             * readers that have not yet drained from the queue.
             */
            return apparentlyFirstQueuedIsExclusive();
        }
    }

    /**
     * 公平同步锁
     */
    static final class FairSync extends Sync {
        private static final long serialVersionUID = -2274990926593161451L;
        final boolean writerShouldBlock() {
            return hasQueuedPredecessors();
        }
        final boolean readerShouldBlock() {
            return hasQueuedPredecessors();
        }
    }

    /**
     * The lock returned by method {@link ReentrantReadWriteLock#readLock}.
     */
    public static class ReadLock implements Lock, java.io.Serializable {
        private static final long serialVersionUID = -5992448646407690164L;
        private final Sync sync;

        /**
         * Constructor for use by subclasses
         *
         * @param lock the outer lock object
         * @throws NullPointerException if the lock is null
         */
        protected ReadLock(ReentrantReadWriteLock lock) {
            sync = lock.sync;
        }

        /**
         * 获取读锁,如果写锁不是由其他线程持有,则获取并立即返回;
         * 如果写锁被其他线程持有,阻塞,直到读锁被获得。
         */
        public void lock() {
            sync.acquireShared(1);
            //ASQ的acquireShared
            /**
             * 以共享模式获取对象,忽略中断。通过至少先调用一次 tryAcquireShared(int)
             * 来实现此方法,并在成功时返回。否则在成功之前,一直调用 tryAcquireShared(int)
             *  将线程加入队列,线程可能重复被阻塞或不被阻塞。
             */
            /*public final void acquireShared(int arg) {
                if (tryAcquireShared(arg) < 0)
                    doAcquireShared(arg);
            }*/
        }

        /**
         * Acquires the read lock unless the current thread is
         * {@linkplain Thread#interrupt interrupted}.
         *
         * 

Acquires the read lock if the write lock is not held * by another thread and returns immediately. * *

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: * *

    * *
  • The read lock is acquired by the current thread; or * *
  • Some other thread {@linkplain Thread#interrupt interrupts} * the current thread. * *
* *

If the current thread: * *

    * *
  • has its interrupted status set on entry to this method; or * *
  • is {@linkplain Thread#interrupt interrupted} while * acquiring the read lock, * *
* * then {@link InterruptedException} is thrown and the current * thread's interrupted status is cleared. * *

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 { sync.acquireSharedInterruptibly(1); } /** * Acquires the read lock only if the write lock is not held by * another thread at the time of invocation. * *

Acquires the read lock if the write lock is not held by * another thread and returns immediately with the value * {@code true}. Even when this lock has been set to use a * fair ordering policy, a call to {@code tryLock()} * will immediately acquire the read lock if it is * available, whether or not other threads are currently * waiting for the read lock. This "barging" 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). * *

If the write lock is held by another thread then * this method will return immediately with the value * {@code false}. * * @return {@code true} if the read lock was acquired */ public boolean tryLock() { return sync.tryReadLock(); } /** * 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 {@linkplain Thread#interrupt * interrupted}. * *

Acquires the read lock if the write lock is not held by * another thread and returns immediately with the value * {@code true}. If this lock has been set to use a fair * ordering policy then an available lock will not 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 {@code tryLock} that does * permit barging on a fair lock then combine the timed and * un-timed forms together: * *

 {@code
         * if (lock.tryLock() ||
         *     lock.tryLock(timeout, unit)) {
         *   ...
         * }}
* *

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: * *

    * *
  • The read lock is acquired by the current thread; or * *
  • Some other thread {@linkplain Thread#interrupt interrupts} * the current thread; or * *
  • The specified waiting time elapses. * *
* *

If the read lock is acquired then the value {@code true} is * returned. * *

If the current thread: * *

    * *
  • has its interrupted status set on entry to this method; or * *
  • is {@linkplain Thread#interrupt interrupted} while * acquiring the read lock, * *
then {@link InterruptedException} is thrown and the * current thread's interrupted status is cleared. * *

If the specified waiting time elapses then the value * {@code false} is returned. If the time is less than or * equal to zero, the method will not wait at all. * *

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 {@code true} if the read lock was acquired * @throws InterruptedException if the current thread is interrupted * @throws NullPointerException if the time unit is null */ public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException { return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout)); } /** * Attempts to release this lock. * *

If the number of readers is now zero then the lock * is made available for write lock attempts. */ public void unlock() { sync.releaseShared(1); } /** * Throws {@code UnsupportedOperationException} because * {@code ReadLocks} 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 {@code "Read locks ="} * 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 = sync.getReadLockCount(); return super.toString() + "[Read locks = " + r + "]"; } } /** * The lock returned by method {@link ReentrantReadWriteLock#writeLock}. */ public static class WriteLock implements Lock, java.io.Serializable { private static final long serialVersionUID = -4992448646407690164L; private final Sync sync; /** * Constructor for use by subclasses * * @param lock the outer lock object * @throws NullPointerException if the lock is null */ protected WriteLock(ReentrantReadWriteLock lock) { sync = lock.sync; } /** * Acquires the write lock. * *

Acquires the write lock if neither the read nor write lock * are held by another thread * and returns immediately, setting the write lock hold count to * one. * *

If the current thread already holds the write lock then the * hold count is incremented by one and the method returns * immediately. * *

If the lock is held by another thread then the current * thread becomes disabled for thread scheduling purposes and * lies dormant until the write lock has been acquired, at which * time the write lock hold count is set to one. */ public void lock() { sync.acquire(1); } /** * Acquires the write lock unless the current thread is * {@linkplain Thread#interrupt interrupted}. * *

Acquires the write lock if neither the read nor write lock * are held by another thread * and returns immediately, setting the write lock hold count to * one. * *

If the current thread already holds this lock then the * hold count is incremented by one and the method returns * immediately. * *

If the 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: * *

    * *
  • The write lock is acquired by the current thread; or * *
  • Some other thread {@linkplain Thread#interrupt interrupts} * the current thread. * *
* *

If the write lock is acquired by the current thread then the * lock hold count is set to one. * *

If the current thread: * *

    * *
  • has its interrupted status set on entry to this method; * or * *
  • is {@linkplain Thread#interrupt interrupted} while * acquiring the write lock, * *
* * then {@link InterruptedException} is thrown and the current * thread's interrupted status is cleared. * *

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 { sync.acquireInterruptibly(1); } /** * Acquires the write lock only if it is not held by another thread * at the time of invocation. * *

Acquires the write lock if neither the read nor write lock * are held by another thread * and returns immediately with the value {@code true}, * setting the write lock hold count to one. Even when this lock has * been set to use a fair ordering policy, a call to * {@code tryLock()} will immediately acquire the * lock if it is available, whether or not other threads are * currently waiting for the write lock. This "barging" * 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). * *

If the current thread already holds this lock then the * hold count is incremented by one and the method returns * {@code true}. * *

If the lock is held by another thread then this method * will return immediately with the value {@code false}. * * @return {@code true} if the lock was free and was acquired * by the current thread, or the write lock was already held * by the current thread; and {@code false} otherwise. */ public boolean tryLock( ) { return sync.tryWriteLock(); } /** * Acquires the write lock if it is not held by another thread * within the given waiting time and the current thread has * not been {@linkplain Thread#interrupt interrupted}. * *

Acquires the write lock if neither the read nor write lock * are held by another thread * and returns immediately with the value {@code true}, * setting the write lock hold count to one. If this lock has been * set to use a fair ordering policy then an available lock * will not be acquired if any other threads are * waiting for the write lock. This is in contrast to the {@link * #tryLock()} method. If you want a timed {@code tryLock} * that does permit barging on a fair lock then combine the * timed and un-timed forms together: * *

 {@code
         * if (lock.tryLock() ||
         *     lock.tryLock(timeout, unit)) {
         *   ...
         * }}
* *

If the current thread already holds this lock then the * hold count is incremented by one and the method returns * {@code true}. * *

If the 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: * *

    * *
  • The write lock is acquired by the current thread; or * *
  • Some other thread {@linkplain Thread#interrupt interrupts} * the current thread; or * *
  • The specified waiting time elapses * *
* *

If the write lock is acquired then the value {@code true} is * returned and the write lock hold count is set to one. * *

If the current thread: * *

    * *
  • has its interrupted status set on entry to this method; * or * *
  • is {@linkplain Thread#interrupt interrupted} while * acquiring the write lock, * *
* * then {@link InterruptedException} is thrown and the current * thread's interrupted status is cleared. * *

If the specified waiting time elapses then the value * {@code false} is returned. If the time is less than or * equal to zero, the method will not wait at all. * *

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 write lock * @param unit the time unit of the timeout argument * * @return {@code true} if the lock was free and was acquired * by the current thread, or the write lock was already held by the * current thread; and {@code false} if the waiting time * elapsed before the lock could be acquired. * * @throws InterruptedException if the current thread is interrupted * @throws NullPointerException if the time unit is null */ public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException { return sync.tryAcquireNanos(1, unit.toNanos(timeout)); } /** * Attempts to release this lock. * *

If the current thread is the holder of this lock then * the hold count is decremented. If the hold count is now * zero then the lock is released. If the current thread is * not the holder of this lock then {@link * IllegalMonitorStateException} is thrown. * * @throws IllegalMonitorStateException if the current thread does not * hold this lock */ public void unlock() { sync.release(1); } /** * Returns a {@link Condition} instance for use with this * {@link Lock} instance. *

The returned {@link Condition} instance supports the same * usages as do the {@link Object} monitor methods ({@link * Object#wait() wait}, {@link Object#notify notify}, and {@link * Object#notifyAll notifyAll}) when used with the built-in * monitor lock. * *

    * *
  • If this write lock is not held when any {@link * Condition} method is called then an {@link * IllegalMonitorStateException} is thrown. (Read locks are * held independently of write locks, so are not checked or * affected. However it is essentially always an error to * invoke a condition waiting method when the current thread * has also acquired read locks, since other threads that * could unblock it will not be able to acquire the write * lock.) * *
  • When the condition {@linkplain Condition#await() waiting} * methods are called the write lock is released and, before * they return, the write lock is reacquired and the lock hold * count restored to what it was when the method was called. * *
  • If a thread is {@linkplain Thread#interrupt interrupted} while * waiting then the wait will terminate, an {@link * InterruptedException} will be thrown, and the thread's * interrupted status will be cleared. * *
  • Waiting threads are signalled in FIFO order. * *
  • The ordering of lock reacquisition for threads returning * from waiting methods is the same as for threads initially * acquiring the lock, which is in the default case not specified, * but for fair locks favors those threads that have been * waiting the longest. * *
* * @return the Condition object */
public Condition newCondition() { return sync.newCondition(); } /** * Returns a string identifying this lock, as well as its lock * state. The state, in brackets includes either the String * {@code "Unlocked"} or the String {@code "Locked by"} * followed by the {@linkplain Thread#getName name} of the owning thread. * * @return a string identifying this lock, as well as its lock state */ public String toString() { Thread o = sync.getOwner(); return super.toString() + ((o == null) ? "[Unlocked]" : "[Locked by thread " + o.getName() + "]"); } /** * Queries if this write lock is held by the current thread. * Identical in effect to {@link * ReentrantReadWriteLock#isWriteLockedByCurrentThread}. * * @return {@code true} if the current thread holds this lock and * {@code false} otherwise * @since 1.6 */ public boolean isHeldByCurrentThread() { return sync.isHeldExclusively(); } /** * Queries the number of holds on this write lock by the current * thread. A thread has a hold on a lock for each lock action * that is not matched by an unlock action. Identical in effect * to {@link ReentrantReadWriteLock#getWriteHoldCount}. * * @return the number of holds on this lock by the current thread, * or zero if this lock is not held by the current thread * @since 1.6 */ public int getHoldCount() { return sync.getWriteHoldCount(); } } // Instrumentation and status /** * Returns {@code true} if this lock has fairness set true. * * @return {@code true} if this lock has fairness set true */ public final boolean isFair() { return sync instanceof FairSync; } /** * Returns the thread that currently owns the write lock, or * {@code null} if not owned. When this method is called by a * thread that is not the owner, the return value reflects a * best-effort approximation of current lock status. For example, * the owner may be momentarily {@code null} even if there are * threads trying to acquire the lock but have not yet done so. * This method is designed to facilitate construction of * subclasses that provide more extensive lock monitoring * facilities. * * @return the owner, or {@code null} if not owned */ protected Thread getOwner() { return sync.getOwner(); } /** * Queries the number of read locks held for this lock. This * method is designed for use in monitoring system state, not for * synchronization control. * @return the number of read locks held */ public int getReadLockCount() { return sync.getReadLockCount(); } /** * Queries if the write lock is held by any thread. This method is * designed for use in monitoring system state, not for * synchronization control. * * @return {@code true} if any thread holds the write lock and * {@code false} otherwise */ public boolean isWriteLocked() { return sync.isWriteLocked(); } /** * Queries if the write lock is held by the current thread. * * @return {@code true} if the current thread holds the write lock and * {@code false} otherwise */ public boolean isWriteLockedByCurrentThread() { return sync.isHeldExclusively(); } /** * Queries the number of reentrant write holds on this lock by the * current thread. A writer thread has a hold on a lock for * each lock action that is not matched by an unlock action. * * @return the number of holds on the write lock by the current thread, * or zero if the write lock is not held by the current thread */ public int getWriteHoldCount() { return sync.getWriteHoldCount(); } /** * Queries the number of reentrant read holds on this lock by the * current thread. A reader thread has a hold on a lock for * each lock action that is not matched by an unlock action. * * @return the number of holds on the read lock by the current thread, * or zero if the read lock is not held by the current thread * @since 1.6 */ public int getReadHoldCount() { return sync.getReadHoldCount(); } /** * Returns a collection containing threads that may be waiting to * acquire the write lock. Because the actual set of threads may * change dynamically while constructing this result, the returned * collection is only a best-effort estimate. The elements of the * returned collection are in no particular order. This method is * designed to facilitate construction of subclasses that provide * more extensive lock monitoring facilities. * * @return the collection of threads */ protected Collection getQueuedWriterThreads() { return sync.getExclusiveQueuedThreads(); } /** * Returns a collection containing threads that may be waiting to * acquire the read lock. Because the actual set of threads may * change dynamically while constructing this result, the returned * collection is only a best-effort estimate. The elements of the * returned collection are in no particular order. This method is * designed to facilitate construction of subclasses that provide * more extensive lock monitoring facilities. * * @return the collection of threads */ protected Collection getQueuedReaderThreads() { return sync.getSharedQueuedThreads(); } /** * Queries whether any threads are waiting to acquire the read or * write lock. Note that because cancellations may occur at any * time, a {@code true} return does not guarantee that any other * thread will ever acquire a lock. This method is designed * primarily for use in monitoring of the system state. * * @return {@code true} if there may be other threads waiting to * acquire the lock */ public final boolean hasQueuedThreads() { return sync.hasQueuedThreads(); } /** * Queries whether the given thread is waiting to acquire either * the read or write lock. Note that because cancellations may * occur at any time, a {@code true} return does not guarantee * that this thread will ever acquire a lock. This method is * designed primarily for use in monitoring of the system state. * * @param thread the thread * @return {@code true} if the given thread is queued waiting for this lock * @throws NullPointerException if the thread is null */ public final boolean hasQueuedThread(Thread thread) { return sync.isQueued(thread); } /** * Returns an estimate of the number of threads waiting to acquire * either the read or write lock. The value is only an estimate * because the number of threads may change dynamically while this * method traverses internal data structures. This method is * designed for use in monitoring of the system state, not for * synchronization control. * * @return the estimated number of threads waiting for this lock */ public final int getQueueLength() { return sync.getQueueLength(); } /** * Returns a collection containing threads that may be waiting to * acquire either the read or write lock. Because the actual set * of threads may change dynamically while constructing this * result, the returned collection is only a best-effort estimate. * The elements of the returned collection are in no particular * order. This method is designed to facilitate construction of * subclasses that provide more extensive monitoring facilities. * * @return the collection of threads */ protected Collection getQueuedThreads() { return sync.getQueuedThreads(); } /** * Queries whether any threads are waiting on the given condition * associated with the write lock. Note that because timeouts and * interrupts may occur at any time, a {@code true} return does * not guarantee that a future {@code signal} will awaken any * threads. This method is designed primarily for use in * monitoring of the system state. * * @param condition the condition * @return {@code true} if there are any waiting threads * @throws IllegalMonitorStateException if this lock is not held * @throws IllegalArgumentException if the given condition is * not associated with this lock * @throws NullPointerException if the condition is null */ 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); } /** * Returns an estimate of the number of threads waiting on the * given condition associated with the write lock. Note that because * timeouts and interrupts may occur at any time, the estimate * serves only as an upper bound on the actual number of waiters. * This method is designed for use in monitoring of the system * state, not for synchronization control. * * @param condition the condition * @return the estimated number of waiting threads * @throws IllegalMonitorStateException if this lock is not held * @throws IllegalArgumentException if the given condition is * not associated with this lock * @throws NullPointerException if the condition is null */ 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 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() { int c = sync.getCount(); int w = Sync.exclusiveCount(c); int r = Sync.sharedCount(c); return super.toString() + "[Write locks = " + w + ", Read locks = " + r + "]"; } /** * 获取线程id */ static final long getThreadId(Thread thread) { return UNSAFE.getLongVolatile(thread, TID_OFFSET); } // Unsafe mechanics private static final sun.misc.Unsafe UNSAFE; private static final long TID_OFFSET; static { try { UNSAFE = sun.misc.Unsafe.getUnsafe(); Class tk = Thread.class; TID_OFFSET = UNSAFE.objectFieldOffset (tk.getDeclaredField("tid")); } catch (Exception e) { throw new Error(e); } } }

你可能感兴趣的:(高并发学习)