ReadWriteLock 如何使用?

版权声明:转载请注名出处 https://blog.csdn.net/meism5/article/details/91366723

ReadWriteLock 如何使用?

ReadWriteLock,读写锁。
ReentrantReadWriteLock 是 ReadWriteLock 的一种实现。

特点:

  • 包含一个 ReadLock 和 一个 WriteLock 对象
  • 读锁与读锁不互斥;读锁与写锁,写锁与写锁互斥
  • 适合对共享资源有读和写操作,写操作很少,读操作频繁的场景
  • 可以从写锁降级到读锁。获取写锁->获取读锁->释放写锁
  • 无法从读锁升级到写锁
  • 读写锁支持中断
  • 写锁支持Condition;读锁不支持Condition

示例1--根据 key 获取 value 值

private ReadWriteLock lock = new ReentrantReadWriteLock();//定义读写锁

//根据 key 获取 value 值
public Object getValue(String key){
	//使用读写锁的基本结构
	lock.readLock().lock();//加读锁
	Object value = null;
	try{
		value = cache.get(key);
		if(value == null){
			lock.readLock().unlock();//value值为空,释放读锁
			lock.writeLock().lock();//加写锁,写入value值
			try{
				//重新检查 value值是否已经被其他线程写入
				if(value == null){
					value = "value";//写入数据
				}
			}finally{
				lock.writeLock().unlock();
			}
			lock.readLock().lock();
		}
	}finally{
		lock.readLock().unlock();
	}
	return value;
}

示例2--多线程环境下的读写锁使用

package constxiong.interview;

import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * 测试可重入 读写锁
 * @author ConstXiong
 * @date 2019-06-10 11:19:42
 */
public class TestReentrantReadWriteLock {
	
	private Map<String, Object> map = new HashMap<String, Object>();
	
	private ReadWriteLock lock = new ReentrantReadWriteLock();
	
	/**
	 * 根据 key 获取 value
	 * @param key
	 * @return
	 */
	public Object get(String key) {
		Object value = null;
		lock.readLock().lock();
		try {
			Thread.sleep(50L);
			value = map.get(key);
		} catch (InterruptedException e) {
			e.printStackTrace();
		} finally {
			lock.readLock().unlock();
		}
		return value; 
	}
	
	/**
	 * 设置key-value
	 * @param key
	 * @return
	 */
	public void set(String key, Object value) {
		lock.writeLock().lock();
		try {
			Thread.sleep(50L);
			map.put(key, value);
		} catch (InterruptedException e) {
			e.printStackTrace();
		} finally {
			lock.writeLock().unlock();
		}
	}

	//测试5个线程读数据,5个线程写数据
	public static void main(String[] args) {
		final TestReentrantReadWriteLock test = new TestReentrantReadWriteLock();
		final String key = "lock";
		final Random r = new Random();
		for (int i = 0; i < 5; i++) {
			new Thread(){
				@Override
				public void run() {
					for (int j = 0; j < 10; j++) {
						System.out.println(Thread.currentThread().getName() + " read value=" + test.get(key));
					}
				}
			}.start();
			
			new Thread(){
				@Override
				public void run() {
					for (int j = 0; j < 10; j++) {
						int value = r.nextInt(1000);
						test.set(key, value);
						System.out.println(Thread.currentThread().getName() + " write value=" + value);
					}
				}
			}.start();
		}
	}
	
}

猜你喜欢

转载自blog.csdn.net/meism5/article/details/91366723