Java 多线程之 ReentrantReadWriteLock(读写锁/共享锁/排他锁)

本文介绍了Java中的ReentrantReadWriteLock,一种读写锁实现,用于在读多写少场景下提升并发性能。它允许并发读取,写操作时独占资源,确保数据一致性和完整性。通过示例展示了如何在实际项目中使用和测试该锁。
摘要由CSDN通过智能技术生成

一、概述

  • 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();
                }
            }
        }
    
    
    }
    
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

QIFU

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值