ReadWriterLock(读写锁)

ReadWriterLock(读写锁)

日常记录
1.6文档解释:
    ReadWriteLock 维护了一对相关的锁,一个用于只读操作,另一个用于写入操作。只要没有 writer,读取锁可以由多个 reader 线程同时保持。写入锁是独占的。

    所有 ReadWriteLock 实现都必须保证 writeLock 操作的内存同步效果也要保持与相关 readLock 的联系。也就是说,成功获取读锁的线程会看到写入锁之前版本所做的所有更新。

    尽管读-写锁的基本操作是直截了当的,但实现仍然必须作出许多决策,这些决策可能会影响给定应用程序中读-写锁的效果。这些策略的例子包括:

  1. 在 writer 释放写入锁时,reader 和 writer 都处于等待状态,在这时要确定是授予读取锁还是授予写入锁。
    Writer优先比较普遍,因为预期写入所需的时间较短并且不那么频繁。Reader优先不太普遍,因为如果 reader
    正如预期的那样频繁和持久,那么它将导致对于写入操作来说较长的时延。公平或者“按次序”实现也是有可能的。
  2. 在 reader 处于活动状态而 writer 处于等待状态时,确定是否向请求读取锁的 reader 授予读取锁。Reader 优先会无限期地延迟 writer,而writer 优先会减少可能的并发。
  3. 确定是否重新进入锁:可以使用带有写入锁的线程重新获取它吗?可以在保持写入锁的同时获取读取锁吗?可以重新进入写入锁本身吗?
  4. 可以将写入锁在不允许其他 writer 干涉的情况下降级为读取锁吗?可以优先于其他等待的 reader 或 writer
    将读取锁升级为写入锁吗?

方法

  1. Lock readLock()
    返回用于读取操作的锁。
  2. Lock writeLock()
    返回用于写入操作的锁。
    优缺点
    优点:
    防止,在多线程下,读写顺序混乱
    缺点:
    写数据时,一次,只允许一个线程写,但是允许多个线程读。
    读数据时,允许多个线程读,但是不允许线程写数据,只有读取完了,才能写数据
    缺点原因:出现写锁的降级,为读锁(写锁可以降级,读锁读锁不可以)
    写锁降级顺序:
    获取写锁----》获取读锁----》释放写锁-----》释放读锁

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

/**
 * 读取锁:ReaderWriterLock
 *    文档:
 *      ReadWriteLock 维护了一对相关的锁,一个用于只读操作,另一个用于写入操作。
 *        只要没有 writer,读取锁可以由多个 reader 线程同时保持。写入锁是独占的。
 *      所有 ReadWriteLock 实现都必须保证 writeLock 操作的内存同步效果也要保持与相关 readLock 的联系。
 *        也就是说,成功获取读锁的线程会看到写入锁之前版本所做的所有更新。
 *    解释:防止,在多线程下,读写顺序混乱
 *    缺点:
 *      写数据时,一次,只允许一个线程写,但是允许多个线程读。
 *      读数据时,允许多个线程读,但是不允许线程写数据,只有读取完了,才能写数据
 *    原因:出现写锁的降级,为读锁(写锁可以降级,读锁读锁不可以)
 *          写锁降级顺序:
 *              获取写锁----》获取读锁----》释放写锁-----》释放读锁
 *
 */
public class ReentrantReadWriterLockUse {
    //模拟缓存
    private static volatile HashMap mp= new HashMap<String,Object>();
    //读写锁可重入锁,解决多线程情况下,读写顺序情况
    private static ReadWriteLock rwLock=new ReentrantReadWriteLock();

    /**
     * 写方法
     * @param key
     * @param value
     */
    public static void writer(String key,Object value){
        rwLock.writeLock().lock();
        //添加写锁
        try {
            //每个写入线程,睡眠0.5秒
            TimeUnit.MILLISECONDS.sleep(10);
            mp.put(key,value);
            System.out.println("正在写入:第"+key+"个值:"+value);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            //释放写锁
            rwLock.writeLock().unlock();
        }

    }

    /**
     * 读方法
     * @param key
     * @return
     */
    public static Object read(String key){
        try {
            //添加读锁
            rwLock.readLock().lock();
            //每个写入线程,睡眠0.5秒
            TimeUnit.MILLISECONDS.sleep(10);
            Object result = mp.get(String.valueOf(key));
            System.out.println("------正在读取:第"+result+"个值:"+result.toString());
            return result;
        } catch (InterruptedException e) {
            e.printStackTrace();
            return "读取失败";
        }finally {
            //释放读锁
            rwLock.readLock().unlock();
        }
    }
    public static void main(String[] args) {
        for (int i = 1; i <=5 ; i++) {
            final int num=i;
        new Thread(()->{
            writer("key"+num,num);
            System.out.println("数据--写入完成:"+"  key:"+num+"  value:"+num);
            }).start();
        }

        for (int i = 1; i <=5 ; i++) {
            final int num=i;
            new Thread(()->{
                Object read =read("key" + num);
                System.out.println("数据--读取完成:"+read.toString());
            }).start();
        }
    }

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Redisson的读写锁是一种特殊的锁机制,它允许多个线程同时占有读模式的锁,但一次只能有一个线程占有写模式的锁。当锁处于写模式时,所有试图对该锁加锁的线程都会被阻塞,直到锁被解锁。当锁处于读模式时,所有试图以读模式对其加锁的线程都可以获得访问权,但如果线程希望以写模式对此锁进行加锁,它必须等待所有的线程释放锁。通常情况下,当锁处于读模式锁定状态时,如果有其他线程试图以写模式加锁,读写锁通常会阻塞随后的读模式锁请求,以避免读模式锁长期占用,而等待的写模式锁请求长期阻塞。读写锁适用于对数据结构的读次数远远多于写次数的情况,因为读模式锁定时可以共享,而写模式锁定时是独占的。[3] 在Redisson中,可以通过以下方式使用读写锁: 1. 获取RedissonClient对象。 2. 使用RedissonClient对象的getReadWriteLock方法获取读写锁对象。 3. 使用读写锁对象的readLock方法获取读锁对象,或使用writeLock方法获取写锁对象。 4. 在需要加锁的代码块中,使用读锁对象的lock方法进行加锁,使用写锁对象的lock方法进行加锁。 5. 在加锁的代码块执行完毕后,使用读锁对象的unlock方法进行解锁,使用写锁对象的unlock方法进行解锁。 例如,在验证读锁的请求中,可以使用RedissonClient对象的getReadWriteLock方法获取读写锁对象,然后使用读锁对象的lock方法进行加锁,读取数据后再使用unlock方法进行解锁。在验证写锁的请求中,可以使用相同的方式获取读写锁对象,然后使用写锁对象的lock方法进行加锁,写入数据后再使用unlock方法进行解锁。[2] 总之,Redisson的读写锁是一种灵活且高效的锁机制,可以在多线程环境下实现对共享资源的安全访问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值