文章目录
- 一、概述
- 二、使用方法
- 三、测试示例
- 四、完整示例
一、概述
-
ReentrantReadWriteLock 是Java中提供的一种读写锁实现,它允许多个线程同时读取共享资源,但在写操作时需要独占访问。它是对传统互斥锁的一种改进,可以提高并发性能。
-
读写锁的主要目的是在读多写少的场景下,提供更高的并发性能。当多个线程只需读取共享资源时,可以同时获得读锁,从而实现并发读取。而当有线程需要对共享资源进行写操作时,它必须独占地获取写锁,在此期间,其他线程无法获取读锁或写锁,从而确保数据的一致性和完整性。
-
读写锁的特性如下:
- 1、多个线程可以同时获取读锁,进行并发读取操作。
- 2、当某个线程获取写锁时,其他线程无法获取读锁或写锁,必须等待写锁释放。
- 3、写锁是独占锁,只能被一个线程获取,用于保证数据一致性。
- 4、ReadWriteLock 接口提供了两个关键的方法:
- (1)readLock():返回一个读锁对象,用于读取共享数据。
- (2)writeLock():返回一个写锁对象,用于写入共享数据。
二、使用方法
-
创建一个
ReentrantReadWriteLock
对象ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
-
获取读锁
rwLock.readLock().lock(); try {// 访问共享资源的读操作 } finally {rwLock.readLock().unlock(); }
-
获取写锁
rwLock.writeLock().lock(); try {// 访问共享资源的写操作 } finally {rwLock.writeLock().unlock(); }
三、测试示例
-
SharedData 类使用 ReentrantReadWriteLock 实现了读写锁机制。多个线程可以同时获取读锁进行读操作,但只有一个线程可以获取写锁进行写操作,以提高读操作的并发性能。
class SharedData {private Map<String, String> data = new HashMap<>();private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();public void put(String key, String value) {lock.writeLock().lock();try {data.put(key, value);} finally {lock.writeLock().unlock();}}public String get(String key) {lock.readLock().lock();try {return data.get(key);} finally {lock.readLock().unlock();}} }
-
测试方法:创建1个写线程,10个读线程。模拟读多写少的场景。
private void test(){SharedData data = new SharedData();List<Thread> threads = new ArrayList();for(int i = 1; i<= 1; i++){Thread t = new Thread(()->{for(int j=0; j< 100000; j++){try {String text = Thread.currentThread().getName()+" 写数据 "+ j;data.put("SharedData", text);System.out.println(text);Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}}});t.setName("写线程"+i);threads.add(t);}for(int i = 1; i<= 10; i++){Thread t = new Thread(()->{for(int j=0; j< 100000; j++){try {String result = data.get("SharedData");System.out.println(Thread.currentThread().getName()+" 读取 "+result);Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}});t.setName("读线程"+i);threads.add(t);}for(Thread t : threads){t.start();}for(Thread t : threads){try {t.join();} catch (InterruptedException e) {e.printStackTrace();}}}
四、完整示例
-
以下是完整示例代码
package top.yiqifu.study.p004_thread;import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.locks.ReentrantReadWriteLock;public class Test062_ReentrantReadWriteLock {public static void main(String[] args) {Test062_ReentrantReadWriteLock test = new Test062_ReentrantReadWriteLock();test.test();}private void test(){SharedData data = new SharedData();List<Thread> threads = new ArrayList();for(int i = 1; i<= 1; i++){Thread t = new Thread(()->{for(int j=0; j< 100000; j++){try {String text = Thread.currentThread().getName()+" 写数据 "+ j;data.put("SharedData", text);System.out.println(text);Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}}});t.setName("写线程"+i);threads.add(t);}for(int i = 1; i<= 10; i++){Thread t = new Thread(()->{for(int j=0; j< 100000; j++){try {String result = data.get("SharedData");System.out.println(Thread.currentThread().getName()+" 读取 "+result);Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}});t.setName("读线程"+i);threads.add(t);}for(Thread t : threads){t.start();}for(Thread t : threads){try {t.join();} catch (InterruptedException e) {e.printStackTrace();}}}class SharedData {private Map<String, String> data = new HashMap<>();private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();public void put(String key, String value) {// 写锁lock.writeLock().lock();try {data.put(key, value);} finally {lock.writeLock().unlock();}}public String get(String key) {// 读锁lock.readLock().lock();try {return data.get(key);} finally {lock.readLock().unlock();}}}}