【并发编程篇】读锁readLock()和写锁writeLock()

2023-12-25 10:38:45


在这里插入图片描述
readLock()和writeLock()都是ReadWriteLock接口中定义的方法,用于获取读锁和写锁。

readLock()方法返回一个读锁,允许多个线程同时获取该锁,以进行并发读取操作。如果当前已有一个写锁或其他线程正在请求写锁,则读锁会被阻塞,直到所有写锁请求完成并释放锁为止。读锁和写锁之间是互斥的。

writeLock()方法返回一个写锁,只允许一个线程获取该锁,以进行写入操作。如果当前已有一个读锁或其他线程正在请求读锁,则写锁会被阻塞,直到所有读锁请求完成并释放锁为止。写锁是独占的,同一时间只能有一个线程持有写锁。

在使用读写锁时,应该根据具体的业务场景和需求选择适当的锁类型。如果共享资源的读取操作远远超过写入操作,那么使用读写锁可以提高系统的并发性能。如果写入操作非常频繁,那么使用读写锁可能会导致读取操作的性能下降,因为读取线程需要等待写入线程释放写锁。此外,读写锁也需要消耗额外的系统资源,因此应该避免不必要的锁竞争。

🛸情景引入

我们先看下面这段代码
在这里插入图片描述

本来应该是1写入,然后1写入完全
但是现在1写入后,紧跟着的是3写入
这明显是错误的

?解决问题

下面我们来加上锁,解决问题

package org.Test6;

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

public class ReadWriteLockDemo {
    public static void main(String[] args) {
        MyCacheLock myCache = new MyCacheLock();

        //写入
        for(int i=1;i<=5;i++){
            final int temp=i;
            new Thread(()->{
                myCache.put(temp+"",temp+"");
            },String.valueOf(i)).start();
        }

        //读取
        for(int i=1;i<=5;i++){
            final int temp=i;
            new Thread(()->{
                myCache.get(temp+"");
            },String.valueOf(i)).start();
        }
    }
}

//自定义缓存
class MyCacheLock{
    private volatile Map<String,Object> map = new HashMap<>();
    private ReadWriteLock readWriteLock = new ReentrantReadWriteLock();

    //存 写 写入的时候
    // 只希望只有一个线程去写
    public void put(String key,Object value){
        readWriteLock.writeLock().lock();  //加锁

        try {
            System.out.println(Thread.currentThread().getName()+"写入"+key);
            map.put("key","value");
            System.out.println(Thread.currentThread().getName()+"写入结束");
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            readWriteLock.writeLock().unlock();  //解锁
        }


    }

    //取 读
    //读的时候,所有人都可以读
    public void get(String key){
        readWriteLock.readLock().lock(); //加锁

        try {
            System.out.println(Thread.currentThread().getName()+"读取"+key);
            Object o=map.get("key");
            System.out.println(Thread.currentThread().getName()+"读取结束");
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            readWriteLock.readLock().unlock(); //解锁
        }


    }
}

在这里插入图片描述

这段代码中,读操作和写操作的主要区别在于使用的锁不同,读操作使用ReadWriteLock实例中的readLock()获取读锁,而写操作使用writeLock()获取写锁。
读写锁允许多个线程同时读取共享资源,但只允许一个线程写入共享资源。因此,在读操作中,多个线程可以同时获得读锁并读取共享资源,而写操作需要获取排他的写锁,以防止其他线程同时写入共享资源。
在MyCacheLock中,put()方法使用writeLock()获取写锁,以确保只有一个线程在写入数据时修改共享资源,而get()方法使用readLock()获取读锁,允许多个线程同时读取数据。
这种读写锁的机制可以提高并发性能,因为允许多个线程同时读取共享资源,而不会产生数据冲突,同时通过只允许一个线程写入共享资源,可以避免写操作的数据竞争和不一致性。

独占锁(写锁):一次只能被一个线程占有
共享锁(读锁):多个线程可以同时占有

在技术的道路上,我们不断探索、不断前行,不断面对挑战、不断突破自我。科技的发展改变着世界,而我们作为技术人员,也在这个过程中书写着自己的篇章。让我们携手并进,共同努力,开创美好的未来!愿我们在科技的征途上不断奋进,创造出更加美好、更加智能的明天!

在这里插入图片描述

文章来源:https://blog.csdn.net/m0_72853403/article/details/135191465
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。