JUC 一 ReentrantReadWriteLock

欢迎光临我的博客[http://poetize.cn],前端使用Vue2,聊天室使用Vue3,后台使用Spring Boot

java.util.concurrent.locks

ReentrantLock是独占锁,一种相对比较保守的锁策略,在这种情况下任何“读/读”、“读/写”、“写/写”操作都不能同时发生
ReentrantReadWriteLock读写锁内部又分为读锁和写锁,读锁可以在没有写锁的时候被多个线程同时持有,写锁是独占的。
在读锁和写锁的获取过程中支持中断 。Condition只有在写锁中用到(读锁是不支持Condition)

简介

一个线程要想同时持有写锁和读锁,必须先获取写锁再获取读锁;写锁可以“降级”为读锁;读锁不能“升级”为写锁。

线程进入读锁的前提条件(在线程持有读锁的情况下,该线程不能取得写锁):

  1. 没有其他线程的写锁

线程进入写锁的前提条件( 在线程持有写锁的情况下,该线程可以继续获取读锁):

  1. 没有其他线程的读锁
  2. 没有其他线程的写锁

读写锁有以下三个重要的特性:
(1)公平选择性:支持非公平(默认)和公平的锁获取方式,吞吐量还是非公平优于公平。
(2)重进入:读锁和写锁都支持线程重进入。
(3)锁降级:遵循获取写锁、获取读锁再释放写锁的次序,写锁能够降级成为读锁。

基本方法

public class ReentrantReadWriteLock implements ReadWriteLock, java.io.Serializable {}
ReentrantReadWriteLock实现了接口ReadWriteLock,该接口提供了两个方法,一个用于获取读锁,另一个用于获取写锁:

public interface ReadWriteLock {
    /**
     * Returns the lock used for reading.
     *
     * @return the lock used for reading
     */
    Lock readLock();
 
    /**
     * Returns the lock used for writing.
     *
     * @return the lock used for writing
     */
    Lock writeLock();
}


ReentrantReadWriteLock

//支持非公平(默认)和公平的锁获取方式,吞吐量还是非公平优于公平
public ReentrantReadWriteLock() {
    this(false);
}
 
public ReentrantReadWriteLock(boolean fair) {
    sync = fair ? new FairSync() : new NonfairSync();
    readerLock = new ReadLock(this);
    writerLock = new WriteLock(this);
}


public int getReadLockCount():当前读锁被获取的次数,但不是占用该锁的线程数,也就是说,一个线程如果n次获取该锁,该方法返回n,而不是1。

public int getReadHoldCount():当前线程获取读锁的次数。

public boolean isWriteLocked():判断写锁是否被获取。

public int getWriteHoldCount():当前线程获取写锁的次数。


ReadLock 

public static class ReadLock implements Lock, java.io.Serializable {
    private static final long serialVersionUID = -5992448646407690164L;
    //持有的AQS对象
    private final Sync sync;

    protected ReadLock(ReentrantReadWriteLock lock) {
        sync = lock.sync;
    }

    //获取共享锁
    public void lock() {
        sync.acquireShared(1);
    }

    //获取共享锁(响应中断)
    public void lockInterruptibly() throws InterruptedException {
        sync.acquireSharedInterruptibly(1);
    }

    //尝试获取共享锁
    public boolean tryLock(long timeout, TimeUnit unit)
            throws InterruptedException {
        return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
    }

    //释放锁
    public void unlock() {
        sync.releaseShared(1);
    }

    //新建条件
    public Condition newCondition() {
        throw new UnsupportedOperationException();
    }

    public String toString() {
        int r = sync.getReadLockCount();
        return super.toString() +
                "[Read locks = " + r + "]";
    }
}

示例

public class ReadWriteLock {

	static ReadWriteLock lock=new ReentrantReadWriteLock();

	static Lock read=lock.readLock();
	static Lock write=lock.writeLock();

	static HashMap<String, Object> map=new HashMap<String, Object>();

	static Object get(String key){
		read.lock();
		try {
			return map.get(key);
		} finally {
			read.unlock();
		}
	}

	static void put(String key,Object value){
		write.lock();
		try {
			map.put(key, value);
		} finally {
			write.unlock();
		}
	}

	static void clear(){
		write.lock();
		try {
			map.clear();
		} finally {
			write.unlock();
		}
	}
}

锁降级示例

锁降级是指把持住(当前拥有的)写锁,再获取到读锁,随后释放(先前拥有的)写锁的过程。

	static Object putAndget(String key,Object value){
		write.lock();
		try {
			read.lock();
			map.put(key, value);
		} finally {
			write.unlock();
		}
		try {
			return map.get(key);
		} finally {
			read.unlock();
		}
		
	}
posted @ 2019-08-26 16:53  LittleDonkey  阅读(182)  评论(0编辑  收藏  举报