Java多线程之读写锁机制

Java多线程中有很多的锁机制,他们都有各自的应用场景,例如今天我说的这种锁机制:读写锁

读写锁,见名知意,主要可以进行两种操作,读和写操作,他们之间结合使用起来又是各不相同的。比如多个线程之间可以同时读,但不可以同时写,也不可以一边读一边写,有点类似于数据库中的共享锁以及排它锁,下面我具体事例演示:

需要注意的是,不管是进行读操作还是写操作,一定要成对去调用方法,就是开启锁后一定要关闭,且为了保险起见,关闭最好要写在finally语句块中去。
另外,我们在声明对象时,有两种方式(有参数和无参数),若为true则为公平机制,默认为false,不写也为false

简单举例演示

package day_12_27;

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

/**
 * @author soberw
 * @Classname ReadWriteLockTest
 * @Description ReadWriteLock的测试
 * @Date 2021-12-27 10:10
 */
public class ReadWriteLockTest {
    public static void main(String[] args) {
        var rwl = new RWL();
        //情况一:
        new Thread(() -> rwl.write(100), "A").start();
        //情况二:
//        new Thread(() -> rwl.write(99), "AA").start();
//        new Thread(() -> rwl.write(88), "AAA").start();

        for (int i = 0; i < 20; i++) {
            new Thread(rwl::read, "B" + i).start();
        }
    }
}

class RWL {
    //可以传参,若为true则为公平锁,默认为false,不写也为false
    private ReadWriteLock rwl = new ReentrantReadWriteLock();
    public int number;


    void write(int number) {
        rwl.writeLock().lock();
        try {
            this.number = number;
            Thread.sleep(2000);
            System.out.println(Thread.currentThread().getName() + ":start--" + number);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            rwl.writeLock().unlock();
        }
    }

    void read() {
        rwl.readLock().lock();
        try {
            Thread.sleep(2000);
            System.out.println(Thread.currentThread().getName() + ":" + number);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            rwl.readLock().unlock();
        }
    }
}

先分析代码,写线程两秒后写入一个线程“A”,然后开启20个读线程都去读数据,结果:
在这里插入图片描述
在写的时候,会停顿两秒,因为我加了sleep(),但是我在读的时候也加了阻塞,却发现20个进程还是同时执行了,这就说明多个进程之间可以同时读,且读写不能同时进行,当线程写的时候,其他所有的读线程都要等着

下面打开情况二,多个线程都进行写操作:
在这里插入图片描述
发现会一个一个执行,间隔两秒,并不会像读操作一样,同时进行,这说明写不能同时进行

应用场景举例

那么在实际开发中,常用这种锁机制来完成缓存系统的操作。所谓缓存系统,举个例子,就比如用户要读取某个数据的时候,我不直接去向数据库请求,而是先看我内部有没有这个数据,如果有就直接返回,如果没有,就从数据库中查找这个数,查到后将这个数据存入我内部存储器中,下次再有人来要这个数据,我就直接返回这个数不用再到数据库中找了,这就大大的避免了频繁的访问数据库。下面我就书写代码模拟这一过程:

package day_12_27;

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

/**
 * @author soberw
 * @Classname ExerData
 * @Description 模拟缓存系统
 * @Date 2021-12-27 20:02
 */
public class ExerData {
    private static ReadWriteLock rwLock = new ReentrantReadWriteLock();

    private static Map<String, Object> map = new HashMap<String, Object>();

    public static void main(String[] args) {
        for (int i = 0; i < 3; i++) {
            final String key = i + "";
            new Thread(new Runnable() {

                @Override
                public void run() {
                    for (int i1 = 0; i1 < 5; i1++) {

                        System.out.println(Thread.currentThread().getName() + " read data: " + getData(key));

                    }
                }
            }).start();
        }
    }

    public static Object getData(String key) {
        rwLock.readLock().lock();
        Object value = null;
        try {
            value = map.get(key);
            if (value == null) {
                rwLock.readLock().unlock();
                rwLock.writeLock().lock();

                try {
                    if (value == null) {
                        // 此处在实际应用中,就是从数据库中查找数据,放入缓存中
                        value = Thread.currentThread().getName() + new Date();
                    }

                } finally {
                    rwLock.writeLock().unlock();
                }
                rwLock.readLock().lock();
            }

        } finally {
            rwLock.readLock().unlock();
        }

        return value;
    }

}

运行结果:
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值