• java中的锁


    前言

    之前的文章在介绍java 的同步和jmm模型的时候,都介绍了synchronized锁。今天我们呢接着java中的锁,来介绍另一种锁的实现方式lock接口。

    Lock接口

    lock出现之前的话,Java就是通过synchronized关键字实现的加锁。但是在javase 5之后,并发包中新增了Lock接口用来实现锁的功能。既然新增了lock接口,那么他肯定是和synchronized关键字在实现锁的方式上有区别的。

    synchronized:隐式的释放和获取锁,使用起来比较方便,但是缺少了对锁的可操作性,将锁的获取和释放固化了。

    lock接口:需要自己手动获取和释放锁,对锁的操作性变强了,而且它可以设置锁的类型(公平锁和非公平锁),但是它也有自己的缺点,那就是不能自动释放锁,如果你忘记释放锁,将会阻塞后续的所有线程。

    上面介绍的只是大概的区别,想要细致的了解,两种锁的区别,可以自行去java官网看使用手册。

    重入锁

    ReetranLock重入锁,顾名思义就是支持可重入的锁,它锁能够支持一个线程对资源的重复加锁。synchronized也是可重入锁。

    重入锁的特点就是当你有了这个锁之后,你再去获取这个锁,不会被阻塞(和加锁一样的道理),这个特性实现需要解决两个问题。
    1.锁的再次获取:锁需要去识别获取锁的线程是不是当前占据锁的线程,如果是,则获取成功。
    2.锁的最终释放:线程重复n次获取了锁,然后释放了n次锁之后,其他线程可以获取到当前的锁(意味着需要有一个计数器记录获取锁的次数,然后在释放锁的时候,将次数减1,当减到为0的时候,为释放成功)。
    ReentranLock是通过组合自定义同步器(之后我们会单独一个章节介绍同步器)实现的。

    公平锁和非公平锁

    公平锁:锁的获取按照先到先得的原则,也就是FIFO。
    非公平锁:大家一起竞争,谁竞争到就算谁的。

    两种锁各有优缺点,非公锁性能会比较好,但是可能会出现有的线程长时间获取不到锁。公平锁性能相对较差,但是不会出现有的线程长时间获取不到锁的情况。所以总的来说,还是非公平锁使用的较多(毕竟性能好)。

    读写锁

    上面介绍的锁,都是排他锁,也就是同一时间只有一个线程可以获取到锁,然后对共享资源进行操作。
    读写锁(ReentrantReadWriteLock)支持同一时间,多个线程操作共享资源。读写锁又分为读锁和写锁。读锁允许同一时间多个线程对共享资源进行访问,但是写锁就不支持了,写是排他锁,同一时间只能有一个线程对共享资源操作。

    读锁和写锁是互斥的,也就是一个共享资源加了写锁之后,其他线程不能获取写锁了,那写锁的线程如果想获取读锁怎么办,可以通过锁降级实现,就是当前线程占有着写锁,然后获取读锁,获取到读锁之后,再释放写锁(一定要是获取到读锁之后再释放写锁,不然再获取到读锁之前,释放写锁,期间有其他线程获取到写锁,修改数据,是对当前线程不可见的)。

    总结

    今天我们通过介绍另一种锁的实现方式Lock接口,将java中的常见的锁的种类给大家进行了简答的介绍,至于每种锁的具体实现,和底层原理,后续章节将会单独介绍。

  • 相关阅读:
    Docker实践经验:Docker 上部署 mysql8 主从复制
    Hyperf使用ElasticSearch记录
    值得收藏的几个postman特色功能帮你事半功倍!
    开源 C++ JSON 库 sonic-cpp解析性能为 rapidjson 的 2.5 倍
    Webpack 解决:ReferenceError: dist is not defined 的问题
    C语言——二周目——程序的翻译与执行环境
    5-1继承的练习
    WPF数据绑定(Binding的源与路径)(二)
    【QT开发(15)】QT在没有桌面的系统中可以使用
    C语言分支和循环语句—for
  • 原文地址:https://blog.csdn.net/qq_41820066/article/details/127736765