【java并发】java ReentrantReadWriteLock学习

大家好,我是walker
一个从文科自学转行的程序员~
爱好编程,偶尔写写编程文章和生活
欢迎关注公众号【I am Walker】,回复“电子书”,就可以获得200多本编程相关电子书哈~
我的gitee:https://gitee.com/shen-chuhao/walker.git 里面很多技术案例!

ReadWriteLock 是什么

  • 首先明确一下,不是说 ReentrantLock 不好,只是 ReentrantLock 某些时候有局限。
    • 如果使用 ReentrantLock,可能本身是为了防止线程 A 在写数据、线程 B 在读数据造成的数据不一致,
  • 但这样,如果线程 C 在读数据、线程 D 也在读数据,读数据是不会改变数据的,没有必要加锁,但是还是加锁了,降低了程序的性能。因为这个,才诞生了读写锁 ReadWriteLock。
  • ReadWriteLock 是一个读写锁接口,读写锁是用来提升并发程序性能的锁分离技术,
  • ReentrantReadWriteLock 是 ReadWriteLock 接口的一个具体实现,实现了读写的分离,读锁是共享的,写锁是独占的,读和读之间不会互斥,读和写、写和读、写和写之间才会互斥,提升了读写的性能。

读写锁的意义

ReadWriteLock 接口的一个具体实现,实现了读写的分离,读锁是共享的,写锁是独占的,读和读之间不会互斥,读和写、写和读、写和写之间才会互斥,提升了读写的性能。

读写锁特性: 3`

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

使用

1、基本使用案例
package lockTest.reentrantReadWriteLock;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * @Author: WalkerShen
 * @DATE: 2022/3/22
 * @Description: 读写锁
 **/
public class ReadWriteLockTest {
    /**
     * public ReentrantReadWriteLock(boolean fair)
     * ReentrantReadWriteLock也可以实现公平锁和非公平锁
     */
    private static ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();

    private final static Lock readLock = readWriteLock.readLock();
    private final static Lock writeLock = readWriteLock.writeLock();
    private final static List<Integer> dataList = new ArrayList<>();

    public static void main(String[] args) {
        new Thread(() -> write()).start();
        new Thread(() -> write()).start();
        new Thread(() -> read()).start();
        new Thread(() -> read()).start();
    }


    /**
     * 读方法
     */
    public static void read() {
        readLock.lock();
        for (Integer data : dataList) {
            System.out.println(Thread.currentThread().getName() + "读取数据:" + data);
        }
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            readLock.unlock();
        }


    }

    /**
     * 写方法
     */
    public static void write() {
        writeLock.lock();
        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread().getName() + "写数据:" + i);
            dataList.add(i);
        }
        writeLock.unlock();

    }

}

结果:

Thread-0写数据:0
Thread-0写数据:1
Thread-0写数据:2
Thread-0写数据:3
Thread-0写数据:4
Thread-1写数据:0
Thread-1写数据:1
Thread-1写数据:2
Thread-1写数据:3
Thread-1写数据:4
Thread-2读取数据:0
Thread-2读取数据:1
Thread-2读取数据:2
Thread-3读取数据:0
Thread-2读取数据:3
Thread-3读取数据:1
Thread-2读取数据:4
Thread-3读取数据:2
Thread-2读取数据:0
Thread-3读取数据:3
Thread-2读取数据:1
Thread-3读取数据:4
Thread-2读取数据:2
Thread-3读取数据:0
Thread-2读取数据:3
Thread-3读取数据:1
Thread-2读取数据:4
Thread-3读取数据:2
Thread-3读取数据:3
Thread-3读取数据:4

从结果中可以发现,写操作的时候只有Thread-0执行完之后才到Thread-1,
而读操作的时候,Thread-2和Thread-3是交替进行的

2、锁升级

在线程中,写锁的级别是大于读锁的,意思是如果不释放读锁,去获取写锁,是获取不到的,会导致线程阻塞
但是如果持有写锁,去获取读锁,是可以获取到的
意思就是说,读锁到写锁,是需要释放后才可以升级的

package lockTest.reentrantReadWriteLock;

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

/**
 * @Author: WalkerShen
 * @DATE: 2022/3/22
 * @Description: 读写锁结合
 **/
public class ReadWriteCombineTest {

    private static ReentrantReadWriteLock readWriteLock=new ReentrantReadWriteLock();
    /**
     * public static class ReadLock implements Lock, java.io.Serializable
     * 因为ReadLock和WriteLock都是静态内部类,所以需要添加static修饰
     */
    private static Lock readLock=readWriteLock.readLock();
    private static Lock writeLock=readWriteLock.writeLock();
    private static String data=null;

    public static void main(String[] args) {
//        new Thread(()->notReleaseReadLock()).start();

        new Thread(()->releaseReadLock()).start();
    }

    /**
     * 读写结合
     * 在写锁操作的时候,没有释放读锁
     * 这个时候就会阻塞
     */
    public static void notReleaseReadLock(){
        readLock.lock();
        if(data==null){
            writeLock.lock();
            data="aaaa";
            System.out.println(data);
            writeLock.unlock();
        }
        readLock.unlock();
    }


    /**
     * 读写结合
     * 在获取写锁之前先释放掉读锁
     * 输出结果:aaaa
     */
    public static void releaseReadLock(){
        readLock.lock();
        if(data==null){
            readLock.unlock();
            writeLock.lock();
            data="aaaa";
            System.out.println(data);
            writeLock.unlock();
        }
    }


}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

WalkerShen

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

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

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

打赏作者

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

抵扣说明:

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

余额充值