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

文章目录


readLock()和writeLock()都是ReadWriteLock接口中定义的方法,用于获取读锁和写锁。

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

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

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

🛸情景引入

我们先看下面这段代码

本来应该是1写入,然后1写入完全

但是现在1写入后,紧跟着的是3写入

这明显是错误的

⭐解决问题

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

java 复制代码
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()获取读锁,允许多个线程同时读取数据。

这种读写锁的机制可以提高并发性能,因为允许多个线程同时读取共享资源,而不会产生数据冲突,同时通过只允许一个线程写入共享资源,可以避免写操作的数据竞争和不一致性。

独占锁(写锁):一次只能被一个线程占有

共享锁(读锁):多个线程可以同时占有

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

相关推荐
数据小爬虫@27 分钟前
Java爬虫实战:深度解析Lazada商品详情
java·开发语言
咕德猫宁丶29 分钟前
探秘Xss:原理、类型与防范全解析
java·网络·xss
songroom29 分钟前
Rust: offset祼指针操作
开发语言·算法·rust
code04号33 分钟前
C++练习:图论的两种遍历方式
开发语言·c++·图论
煤泥做不到的!2 小时前
挑战一个月基本掌握C++(第十一天)进阶文件,异常处理,动态内存
开发语言·c++
F-2H2 小时前
C语言:指针4(常量指针和指针常量及动态内存分配)
java·linux·c语言·开发语言·前端·c++
苹果酱05672 小时前
「Mysql优化大师一」mysql服务性能剖析工具
java·vue.js·spring boot·mysql·课程设计
_oP_i3 小时前
Pinpoint 是一个开源的分布式追踪系统
java·分布式·开源
mmsx3 小时前
android sqlite 数据库简单封装示例(java)
android·java·数据库
bryant_meng3 小时前
【python】OpenCV—Image Moments
开发语言·python·opencv·moments·图片矩