Java多线程 ReadWriteLock读写锁的使用

Java多线程 ReadWriteLock读写锁的使用

1、ReadWriteLock 简介

(1)ReadWriteLock接口的实现类-ReentrantReadWriteLock读写锁两个锁,一个是读操作相关的锁也成为共享锁,一个是写操作相关的锁 也称为排他锁。通过分离读锁和写锁,其并发性比一般排他锁有了很大提升。

锁的特点:
1、多个读锁之间不互斥,
2、读锁与写锁互斥,
3、写锁与写锁互斥(只要出现写操作的过程就是互斥的。)

在没有线程Thread进行写入操作时,进行读取操作的多个Thread都可以获取读锁,而进行写入操作的Thread只有在获取写锁后才能进行写入操作。即多个Thread可以同时进行读取操作,但是同一时刻只允许一个Thread进行写入操作。

(2)ReentrantReadWriteLock的特性

特性 说明
可重入性 该锁支持可重入,以读写线程为例:读线程在获取了读锁之后,能够再次获取读锁。而写线程在获取了写锁之后能够再次获取写锁也能够同时获取读锁
锁降级 写锁能够降级称为读锁,并遵循获取写锁、获取读锁再释放写锁的次序
公平性选择 支持非公平(默认)和公平的锁获取方式,吞吐量上来看还是非公平优于公平

(3)ReentrantReadWriteLock常见构造方法

ReentrantReadWriteLock(): 创建一个 ReentrantReadWriteLock()的实例

ReentrantReadWriteLock(boolean fair) :创建一个特定锁类型(公平锁/非公平锁)的ReentrantReadWriteLock的实例

2、实例:读者写者问题

读者—写者问题(Readers-Writers problem)也是一个经典的并发程序设计问题,是经常出现的一种同步问题。计算机系统中的数据(文件、记录)常被多个进程共享,但其中某些进程可能只要求读数据(称为读者Reader);另一些进程则要求修改数据(称为写者Writer)。就共享数据而言,Reader和Writer是两组并发进程共享一组数据区,要求:

(1)允许多个读者同时执行读操作;

(2)不允许读者、写者同时操作;

(3)不允许多个写者同时操作。

下面是ReentrantReadWriteLock的代码实现:

package chat7;

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

public class ReadWriteLockTest {
//内部类
class DataBase {
    private Object data = null;// 共享数据,只能有一个线程能写该数据,但可以有多个线程同时读该数据。
    private ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(false);

    public void get() {
        rwl.readLock().lock();// 上读锁,其他线程只能读不能写
        System.out.println("线程:" + Thread.currentThread().getName()
                + " 正在准备读取数据");
        try {
            Thread.sleep((long) (Math.random() * 1000));
            System.out.println(Thread.currentThread().getName()
                    + "读到的数据为:" + data);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            rwl.readLock().unlock(); // 释放读锁
        }
    }

    public void put(Object data) {
        rwl.writeLock().lock();// 上写锁,不允许其他线程读也不允许写
        System.out.println(Thread.currentThread().getName()
                + " 正准备写进数据");
        this.data = data;
        System.out.println(Thread.currentThread().getName()
                + " 已经写进数据 " + data);
        try {
            Thread.sleep((long) (Math.random() * 1000));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            rwl.writeLock().unlock();// 释放写锁
        }
    }
   public static void main(String[] args) {
        final DataBase q = new DataBase();
        for (int i = 0; i < 2; i++) { //创建两个读者线程
            new Thread() {
                public void run() {
                    while (true) {
                        q.get();
                    }
                }
            }.start();
        }
        for (int i = 0; i < 2; i++) { //创建两个写者进程
            new Thread() {
                public void run() {
                    while (true) {
                        q.put(new Random().nextInt(10000));
                    }
                }
            }.start();
        }
    }
}
}

在这里插入图片描述

3、总结

(1)ReentrantReadWriteLock的拥有三大特性:
可重入性,降级锁,公平性选择;
(2)锁的三大特点:
1、多个读锁之间不互斥,
2、读锁与写锁互斥,
3、写锁与写锁互斥(只要出现写操作的过程就是互斥的。)

发布了26 篇原创文章 · 获赞 16 · 访问量 2141

猜你喜欢

转载自blog.csdn.net/qqq3117004957/article/details/104577353