Java中的各种锁,容易理解_锁的理解,用到哪些锁-程序员宅基地

技术标签: Java中的各种锁  java  乐观锁和悲观锁  

转载自WX公众号:https://mp.weixin.qq.com/s/WSZV5l5dlieJ8YxSit6Qug

作者:乱敲代码

说到了锁我们经常会联想到生活中的锁,在我们日常中我们经常会接触到锁。比如我们的手机锁,电脑锁,再比如我们生活中的门锁,这些都是锁。

锁有什么作用呢?

说了这么多还是不清楚锁到底有什么用处?这一点就要深思我们为什么要使用锁,我们用手机锁是为了保障我们的隐私安全,使用门锁是为了保障我们的财产安全,准确的来说我们使用锁就是为了安全。那么在生活中我们可以加锁来保障自己的隐私和财产安全,那Java中的锁有什么用处呢?

Java中的锁

Java中的锁准确的来说也是为了保证安全,不过不同的是Java中的锁是为了保证并发所需要的。所以在Java中加锁准确的来说是为了保证并发安全,同时也是为了解决内存中的一致性,原子性,有序性三种问题。在Java中提供了各式各样的锁,每种锁都有其自身的特点和适用范围。所以我们都要熟悉锁的区别和原理才能正确的使用。

乐观锁和悲观锁

悲观锁

乐观锁和悲观锁的话在之前我刚刚开始写的时候就写过相关的文章,在这里就重新介绍一下吧。悲观锁如其名它是悲观的,它觉得每次访问数据都可能被其他人(线程)修改,所以在访问资源的时候就会对资源进行加锁,用这种方式来保证资源在访问的时候不会被其他线程修改。这样的话其他线程想要获取资源的话就只能阻塞,等到当前线程释放锁后在获取。在Java中悲观锁的实现有synchronized关键字Lock的实现类都是悲观锁。我们来看一下悲观锁到底是怎么执行的。

线程A抢占到资源后线程B就陷入了阻塞中,然后就等待线程A释放资源。

 

当线程A释放完资源后线程B就去获取锁开始操作资源˛悲观锁保证了资源同时只能一个线程进行操作。

乐观锁

与悲观锁相反,乐观锁并不会觉得访问数据的时候会有人修改(所以它是乐观的),所以在访问资源的时候并不会上锁,但是在提交的时候回去判断一下是否有人修改了当前数据,在数据库中我们可以使用version版本号去实现。在Java中我们是使用CSA来实现。我们看一下乐观锁的执行过程

CAS

CAS(Compare And Swap)算法是一种无锁算法,是Java提供的非阻塞原子性操作。在不使用锁的情况下实现多线程下的同步。在并发包中(java.util.concurrent)原子性类都是使用CAS来实现乐观锁的。CAS通过硬件保证了比较更新的原子性,在JDK中Unsafe提供了一系列的compareAndSwap*方法,这里就不深究Unsafe这个类了。CAS操作过程就是将内存中的将要被修改的数据与预期的值进行比较,如果这两个值相等就修改值为新值,否则就不做操作也就是说CAS需要三个操作值:

  • 预期值的 A

  • 内存中的V

  • 将要修改的B

简单的来说CAS就是一个死循环,在循环中判断预期的值和内存中的值是否相等,如果相等的话就执行修改,如果如果不相等的话就继续循环,直到执行成功后退出。

CAS的问题

CAS虽然很牛逼但是它也存在一些问题比如ABA问题,举个例子,现在有内存中有一个共享变量X的值为A,这个时候出现一个变量想要去修改变量X的值,首先会获取X的值这个时候获取的是A,然后使用CAS操作把X变量修改成B。这样看起来是没有问题,那如果在线程1获取变量X之后,执行CAS之前出现一个线程2把X的值修改成B然后CAS操作执行又修改成了了A,虽然最后执行的结果共享变量的值为A但是此A已经不是线程1获取的A了。这就是经典的ABA问题。产生ABA问题是因为变量的状态值发生了环形转换,A可以到B,B可以到A,如果A到B,B到C就不会发生这种问题。

解决办法:在JDK1.5后加入了AtomicStampedReference方法给每个变量加入了一个时间戳来避免ABA问题。

同时CAS还有循环开销大的问题,因为会一直循环直到预期和内存相等修改成功。同时还有只能保证一个共享变量的原子性的问题不过在JDK1.5之后加入了AtomicReference类来保证引用对象之间的原子性。

使用悲观锁和乐观锁

 

可以使用synchronized关键字来实现悲观锁,乐观锁可以使用并法包下提供的原子类。

公平锁和非公平锁

上面说了悲观锁和乐观锁,现在来看公平锁和非公平锁。在锁中也是有公平和不公平滴,公平锁如其名讲究的是一个公平,所以多个线程同时申请申请锁的话,线程会放入一个队列中,在队列中第一个进入队列的线程才能获取锁资源,讲究的是先到先得。就比如我们在学校食堂打饭的时候,那个时候记得我同学一放学就赶快去食堂排队这样的话才能尽快的打上饭,而且在排队的过程中并不会有人吃不到饭,这个时候食堂阿姨是公平的每个人排队的话都能吃到饭,线程也是如此。非公平锁可以这样理解,我那个同学去食堂排队打饭了但是有人却插队,食堂阿姨却不公平直接给插队的人打饭却不给他打,你说气不气是不是很不公平,划重点非公平锁先到不一定先得。不过公平锁也是有缺点的,当一个线程获取资源后在队列中的其他的线程就只能在阻塞,CPU的所以公平锁比非公平锁的效率要低很多。因为CPU唤醒阻塞线程的开销比非公平锁大。我们来看一个一个例子:

在Java中ReentrantLock提供了公平锁和非公平锁的实现。看一下ReentrantLock怎么实现公平锁和非公平锁

 

使用公平锁和非公平锁

ReentrantLock默认就是非公平的锁,我们来看一下公平锁的例子:

看一下输出结果:

我们可以看到公平锁的输出结果是按照顺序来的,先到先得。在看一下非公平锁的例子:

输出结果:

我们可以看到如果使用非公平锁的话最后输出的结果是完全没有顺序的,先到不一定先得。所以在使用公平锁的时候线程1获取到锁之后线程2在请求锁的话就会挂起等待线程1释放锁,然后线程2才能获取锁。如果再有一个线程3想要请求锁的话,这时候如果使用的是非公平锁,那么线程2和线程3中两个有一个会获取到锁,公平锁的情况下线程3只能先挂起,等待线程2获取锁资源释放后在获取。

什么时候使用公平锁和非公平锁

在需要公平资源的场景下使用公平锁,如果不需要特殊的公平对待的话尽量使用非公平锁,因为公平锁会带来性能的开销。

独占锁和共享锁

看到独占和共享会联想到什么,对的独占锁就是每次只有一个线程能霸占这个锁资源,而其他线程就只能等待当前获取锁资源的线程释放锁才能再次获取锁,刚刚上面的ReentrantLock就是独占锁,那这样看来独占锁不也就是悲观锁吗?因为悲观锁抢占资源后就只能等待释放其他线程才能再次获取到锁资源。其实准确的说独占锁也是悲观锁。在谈共享锁,共享锁其实也是乐观锁它放宽了锁的策略允许多个线程同时获取锁。在并发包中ReadWriteLock就是一个典型的共享锁。它允许一个资源可以被多个读操作访问,或者被一个 写操作访问,但两者不能同时进行。

自旋锁

什么是自旋锁,自旋锁其实就是当一个线程获取锁的时候,这个锁已经被其他人获取到了那么这个线程不会立马挂起,反而在不放弃CPU使用权的情况下会尝试再次获取锁资源,默认次数是10次,可以使用-XX: PreBlockSpinsh来设置次数。如果自旋锁获取锁的时间太长,会造成后面的线程CPU资源耗尽释放。并且自旋锁是不公平的。

优点

自旋锁不会使线程状态发生切换,一直处于用户态,即线程一直都是active的;不会使线程进入阻塞状态,减少了不必要的上下文切换,执行速度快。

 

关注我的公众号:程序员小栈
一起来交流学习吧

 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/Dream_xun/article/details/102472010

智能推荐

Linux 内核优化简笔 - 高并发的系统-程序员宅基地

文章浏览阅读1.3k次,点赞31次,收藏17次。Linux 服务器在高并发场景下,默认的内核参数无法利用现有硬件,造成软件崩溃、卡顿、性能瓶颈。当然,修改参数只是让Linux更好软件的去利用已有的硬件资源,如果硬件资源不够也无法解决问题的。而且当硬件资源不足的时候,某些参数过大可能也会占用多余资源,或者影响稳定性。或者让单个进程占用过多资源,影响整体系统的运行。写本文的起因主要是对zabbix 服务器的高并发需求,还有数据库、Nginx、ES集群的高并发需求。more。

手把手教你如何使用Zotero自定义参考文献格式(csl)_zotero csl-程序员宅基地

文章浏览阅读7.1w次,点赞119次,收藏312次。一、使用Zotero如何查找合适的引用和参考文献格式?通过下面这个网站可以找到合适的格式https://editor.citationstyles.org/about/假如你有一份参考文献格式要求,可以通过search by example(红色箭头位置)查找格式的名称。例如:在左边区域选择文献的类型(箭头位置)。文献的类型分为以下几种:论文(thesis)、专著章节或文集(chapter)、杂志论文(article-journal)、报道(report)、著作(book)、网络(webpa_zotero csl

Python中,如何删除字典中的键(键明明存在,却报KeyError: ‘xxx‘)【PS:已解决、附代码】_python字典删除元素 del keyerror-程序员宅基地

文章浏览阅读2.7k次。最近在使用Python做仿真实验,没想到搞得我心力憔悴,那叫一个头大啊!错误无限循环,bug“永无止境”,很想…(此处省略一万字)。好了,不给大家叨唠传递负能量了,直接上干货。问题描述:大家在对Python的学习中或者使用中..._python字典删除元素 del keyerror

eureka集群_eureka集群搭建-程序员宅基地

文章浏览阅读171次。目标Eureka集群搭建Eureka自我保护机制Eureka集群搭建高可用集群配置当注册中心扛不住高并发的时候,这时候 要用集群来扛;普通操作新建两个简单的springboot模块module microservice-eureka-server-2002 microservice-eureka-server-20031、pom.xml 把依赖加下:<dependenci..._eureka集群搭建

BERT在语言翻译中的挑战:如何克服语言差异_bert是否适合用于翻译问题-程序员宅基地

文章浏览阅读866次,点赞19次,收藏23次。1.背景介绍语言翻译是自然语言处理领域的一个重要任务,它涉及将一种语言中的文本翻译成另一种语言。随着大数据时代的到来,语言翻译技术的发展得到了重要的推动。随着深度学习技术的发展,语言翻译技术也从传统的统计模型逐渐转向深度学习模型。在2018年,Google发布了BERT(Bidirectional Encoder Representations fr_bert是否适合用于翻译问题

JSON数据结构(A、快速入门篇)(Yanlz+Data+JsonArray+JsonObject+JsonValue+JsonMapper.ToJson+JsonMapper.ToObject+)_jsonmapper.toobject获取的信息是什么类型-程序员宅基地

文章浏览阅读3.4k次。《JSON数据结构》 版本 作者 参与者 完成日期 备注 Data_JSON_V01_1.0 严立钻 2018.08.24 ..._jsonmapper.toobject获取的信息是什么类型

随便推点

防火墙之Firewalld_firewalld清除所有规则-程序员宅基地

文章浏览阅读435次。1 firewalld 防火墙简介1.1​ firewalld 和 iptables 的关系1.2 firewalld 和 iptables 的区别1.3 firewalld 区域的概念1.3.1 firewalld 防火墙预定义了9个区域1.3.2 firewalld 网路区域1.3.3 firewalld 数据处理流程2 firewalld 防火墙的配置方法2.1 firewalld 服务管理2.2 区域管理2.3 服务管理2.4 端口管理补充 firewalld 设置 SNAT_firewalld清除所有规则

【AI大模型】WikiChat超越GPT-4:在模拟对话中事实准确率提升55%终极秘密_wikichat模型-程序员宅基地

文章浏览阅读1.2k次,点赞34次,收藏19次。通过将多个模型进行组合或集成,可以充分利用各个模型的优点,提高整体模型的适应性。例如,使用集成学习方法(如随机森林、梯度提升等)可以将多个弱模型组合成一个强模型,从而提高模型的预测精度和稳定性。_wikichat模型

重温 DOS _dos 下 edit 下载-程序员宅基地

文章浏览阅读1.7k次。DOS常用命令要想操作使用DOS,知道一些常用命令是非常重要的。以下是一些命令的用法。文件名是由文件路径和文件名称合起来的,如C:/DOS/COMMAND.COM。DIR 显示文件和文件夹(目录)用法:DIR [文件名] [选项]它有很多选项,如/A表示显示所有文件(即包括带隐含和系统属性的文件),/S表示也显示子文件夹中的文件,/P表示分屏显示,/B表示只显示文件名,等等。如_dos 下 edit 下载

Failed to execute goal org.codehaus.mojo:exec-maven-plugin:3.0.0:exec (default-cli) on project Hello_failed to exectue goal org.codehaus.mojo-程序员宅基地

文章浏览阅读3.3k次。HBASE只是添加了一句话,运行就出现如下错误Failed to execute goal org.codehaus.mojo:exec-maven-plugin:3.0.0:exec (default-cli) on project HelloSpring: Command execution failed.解决:在pom.xml中添加 <build> <pluginManagement><!-- lock down plugins version_failed to exectue goal org.codehaus.mojo

HTTP基本原理(简介)-程序员宅基地

文章浏览阅读1.6w次,点赞16次,收藏57次。原文:http://blog.csdn.net/hguisu/article/details/86808081. HTTP简介 HTTP协议(HyperText Transfer Protocol,超文本传输协议)是用于从WWW服务器传输超文本到本地浏览器的传送协议。它可以使浏览器更加高效,使网络传输减少。它不仅保证计算机正确快速地传输超文本文档,还确定传输_http基本原理

小程序云开发获取不到openId_setting data field "openid" to undefined is invali-程序员宅基地

文章浏览阅读457次。Setting data field "openId" to undefined is invalid_setting data field "openid" to undefined is invalid.

推荐文章

热门文章

相关标签