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

智能推荐

第一章-第七题( 有人认为,“中文编程”, 是解决中国程序员编程效率一个秘密武器,请问它是一个 “银弹” 么? )--By 侯伟婷...-程序员宅基地

文章浏览阅读208次。  首先,“银弹”在百度百科中的解释是银色的子弹,我们更熟知的“银弹”一词,应该是在《人月神话》中提到的。银弹原本应该是指某种策略、技术或者技巧可以极大地提高程序员的生产力【1】。此题目中关于中文编程是否是一个“银弹”的讨论,我所持的是否定的态度,我不认为中文编程会是一项提高中国程序员编程效率的一个秘密武器,相反,我还认为他会比现在的英文编程来说降低工作效率,造成很大的工作上的困难。..._存在一种策略,技术技巧可以极大的提高程序员的生产力。

模拟用户操作 京东抢购 华为mate40 Pro、支付的js脚本_京东抢华为脚本-程序员宅基地

文章浏览阅读5.4k次,点赞2次,收藏29次。1 登录 https://item.jd.com/10024680695127.html2 打开开发者模式,插入如下代码,count=1nIntervId=0 stop=0 var goDate function start(){ if (stop==1){ clearInterval(nIntervId);//停止监控 return } if (Date.now() < goDate){ return _京东抢华为脚本

php eayswoole node axios crypto-js 实现大文件分片上传复盘_cryptojs 处理文件过大-程序员宅基地

文章浏览阅读740次。1)前端侧 :前端上传文件,根据分片大小,自动计算出整个文件的分片数量,以及分片二进制文件,以及整个文件的md5值,以及分片文件md5值,传与后端,后端处理完后,根据上传分片的进度以及后端返回状态,判断整个文件是否传输完毕,完毕后,前端展示完成进度。2)后端PHP侧:后端接收前端传过来的数据,包括文件名,文件md5,分片信息,然后将分片文件信息存储到redis 有序集合中,其中key为整个文件的md5 ,待所有分片文件都上传完后,根据顺序,然后将文件整合存储,然后完成整个文件分片上传逻辑。_cryptojs 处理文件过大

VScode 编译器配置IDE环境(C/C++/Go)_vscode 配置 在ide上编译运行-程序员宅基地

文章浏览阅读4.5k次,点赞4次,收藏29次。VScode 编译器配置IDE环境(C/C++/Go)摘要VS Code 下载安装下载安装简单使用WindowsLinuxIDE 环境配置C/C++C/C++ 编译器安装及配置简单使用 VS Code 终端进行编译和运行方式使用code runner插件:Go总结摘要对于 VS Code 的使用,我本人感觉这个编译器还是很好用的,而且目前能够支持在 Windows、Linux、MacOs 上流畅运行,并且官方已经提供了 X86、ARM等主流架构版本,还很容易通过安装插件就能过实现基于 SSH 的远程代_vscode 配置 在ide上编译运行

oracle use_ntl详细解释_oracle中use_nl提示-程序员宅基地

文章浏览阅读1k次。1./*+ use_nl(t2,t) */提示走nest Loop,但是没有提示t2还是t为驱动表2./*+ ordered user_nl(t2,t) */提示走 Nest Loop,order提示的是from 后面的第一个表为驱动表.3./*+ leading(t2) use_nl(t) */直接提示t2为驱动表。结论:use_NL不能让优化器确定谁是驱动表谁是被驱动表。use_nl(t,t2)也没有指出哪个是驱动表,这时候我们就需要使用Ordered ,_oracle中use_nl提示

windows下python2.7 media模块的安装_python下载media模块-程序员宅基地

文章浏览阅读1.2k次。总共就是需要以上这些安装包(这里面python-2.7.4.msi是python的安装包)关于pygraphics的模块可以到http://code.google.com/p/pygraphics/downloads/list下载,下载时要看好针对的操作系统和python的版本号。找不到的就百度吧,最好是到官网上下载。安装步骤:下载:Python Ima_python下载media模块

随便推点

5、Nacos 、Sentinel、Seata下载与安装_sentinel下载安装-程序员宅基地

文章浏览阅读1.8k次,点赞2次,收藏10次。1、官网:https://nacos.io/zh-cn/index.html2、 下载3、解压安装双击startup.cmdjava.io.IOException: java.lang.IllegalArgumentException: db.num is null如果出现以上错误,需要指令启动:单机模式启动 window版本 startup.cmd -m standalone4、访问登录http://localhost:8848/nacos/index.html#/._sentinel下载安装

linux ssh远程登录退出,ssh登陆小技巧-用SSH 退出符切换 SSH 会话-程序员宅基地

文章浏览阅读1.7k次。用SSH 退出符切换 SSH 会话这个技巧非常实用。尤其是远程登陆到一台主机A,然后从A 登陆到B,如果希望在A 上做一些操作,还得再开一个终端,很是麻烦。当你使用ssh从本机登录到远程主机时,你可能希望切换到本地做一些操作,然后再重新回到远程主机。这个时候,你不需要中断 ssh连接,只需要按照如下步骤操作即可:当你已经登录到了远程主机时,你可能想要回到本地主机进行一些操作,然后又继续回到远程主机..._linux中ssh远程登录后如何回到原来主机

[渝粤教育] 四川农业大学 计算机网络 参考 资料_调制的信号是单一频率的载波信号吗-程序员宅基地

文章浏览阅读796次。教育-计算机网络-章节资料考试资料-四川农业大学【】随堂测验1、【单选题】以下哪一项不属于物联网的实现基础A、可穿戴设备B、RFIDC、APPD、蓝牙参考资料【 】2、【单选题】以下哪一项不是解决网络安全问题的因素A、 安全技术B、法律法规C、道德自律D、多种应用参考资料【 】电路交换随堂测验1、【单选题】以下哪一项不是电路交换的特征A、按需建立点对点信道B、数据无需携带地址信息C、点对点信道独占经过的物理链路带宽D、两两终端之间可以同时通信参考资料_调制的信号是单一频率的载波信号吗

吃透这几道MQ消息队列面试题,秒杀面试官..._mq面试题吊打面试官-程序员宅基地

文章浏览阅读450次。几种常见的MQ面试题相关视频参考(来自动力节点):https://www.bilibili.com/video/BV1Ap4y1D7tU相关资料下载:http://www.bjpowernode.com/?csdn为什么使用消息队列?其实就是问问你消息队列都有哪些使用场景,然后你项目里具体是什么场景,说说你在这个场景里用消息队列是什么?面试官问你这个问题,期望的一个回答是说,你们公司有个什么业务场景,这个业务场景有个什么技术挑战,如果不用 MQ 可能会很麻烦,但是你现在用了 MQ 之后带_mq面试题吊打面试官

《UnityAPI.Screen屏幕》(Yanlz+Unity+SteamVR+云技术+5G+AI+VR云游戏+Unity+Screen+dpi+SetResolution+立钻哥哥++OK++)_unity刷新屏幕的api-程序员宅基地

文章浏览阅读1.5k次。《UnityAPI.Screen屏幕》 Screen屏幕 版本 作者 参与者 完成日期 备注 UnityAPI_Screen_V01_1.0 严立钻 2020.09.16 ..._unity刷新屏幕的api

流媒体服务器SRS的搭建及QT下RTMP推流客户端的编写_开源srs流媒体服务器-程序员宅基地

文章浏览阅读2.4k次。本客户端基于我的博客:https://blog.csdn.net/linyibin_123/article/details/132107948 开发的播放器下新增RTMP推流。播放器可以支持软硬解码,截图、录像等功能,详细功能看该博客。本客户端支持读取文件解码后推流,也支持拉取网络流解码后进行推流。推流地址为前面搭建的RTMP流媒体服务器,推流成功后,通过VLC播放器从RTMP服务器上拉流下来播放。_开源srs流媒体服务器

推荐文章

热门文章

相关标签