乐观锁和悲观锁_什么是悲观锁和乐观锁?

b384104b12ccc78be0c67480593003dc.png

思维导图

a365024e589c2752f36067a8fc56c687.png
文章已收录Github精选,欢迎Star:https://github.com/yehongzhi/learningSummary

悲观锁

悲观锁是平时开发中经常用到的一种锁,比如ReentrantLocksynchronized等就是这种思想的体现,它总是假设别的线程在拿线程的时候都会修改数据,所以每次拿到数据的时候都会上锁,这样别的线程想拿这个数据就会被阻塞。如图所示:

eee323890517d1977c75c999c9c4589c.png

synchronized是悲观锁的一种实现,一般我们都会有这样使用:

private static Object monitor = new Object();public static void main(String[] args) throws Exception {//锁一段代码块synchronized (monitor){}
}
//锁实例方法,锁对象是this,即该类实例本身
public synchronized void doSome(){}
//锁静态方法,锁对象是该类,即XXX.class
public synchronized static void add(){}

我们以最简单的同步代码块来分析,其实就是将synchronized作用于一个给定的实例对象monitor,即当前实例对象就是锁对象,每次当线程进入synchronized包裹的代码块时就会要求当前线程持有monitor实例对象锁,如果当前有其他线程正持有该对象锁,那么新到的线程就必须等待,这样也就保证了每次只有一个线程执行synchronized内包裹的代码块

从上面的分析中可以看出,悲观锁是独占和排他的,只要操作资源都会对资源进行加锁。假设读多写少的情况下,使用悲观锁的效果就不是很好。这时就引出了接下来要讲的乐观锁。

乐观锁

乐观锁,顾名思义它总是假设最好的情况,线程每次去拿数据时都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,如果这个数据没有被更新,当前线程将自己修改的数据成功写入。如果数据已经被其他线程更新,则根据不同的实现方式执行不同的操作(例如报错或者自动重试)。如图所示:

6d29dd17d5812b1592419d2d0cf9e185.png

一般乐观锁在java中是通过无锁编程实现的,最常见的就是CAS算法,比如Java并发包中的原子类的递增操作就是通过CAS算法实现的。

CAS算法,其实就是Compare And Swap(比较与交换)的意思。目的就是将内存的值更新为需要的值,但是有个条件,内存值必须与期待的原内存值相同。展开来说,我们有三个变量,内存值M,期望的内存值E,更新值U,只有当M==E时,才会将M更新为U

CAS算法实现的乐观锁在很多地方有应用,比如并发包的原子类AtomicInteger类。在自增的时候就使用到CAS算法。

public final int getAndIncrement() {return unsafe.getAndAddInt(this, valueOffset, 1);
}//var1 是this指针
//var2 是偏移量
//var4 是自增量
public final int getAndAddInt(Object var1, long var2, int var4) {int var5;do {//获取内存,称之为期待的内存值Evar5 = this.getIntVolatile(var1, var2);//var5 + var4的结果是更新值U//这里使用JNI方法,每个线程将自己内存中的内存值M与var5期望值比较,//如果相同则更新为var5 + var4,返回true跳出循环。//如果不相同,则把内存值M更新为最新的内存值,然后自旋,直到更新成功为止} while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));//返回更新后的值return var5;
}public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);

所以可以看出CAS算法其实是无锁的。好处是在读多写少的情况下,性能是比较好的。那么CAS算法的缺点其实也是很明显的。

  • ABA问题。线程C将内存值A改成了B后,又改成了A,而线程D会认为内存值A没有改变过,这个问题就称为ABA问题。解决办法很简单,在变量前面加上版本号,每次变量更新的时候变量的版本号都+1,即A->B->A就变成了1A->2B->3A
  • 在写多读少的情况下,也就是频繁更新数据,那么会导致其他线程经常更新失败,那么就会进入自旋,自旋时会占用CPU资源。如果资源竞争激烈,多线程自旋的时间长,导致消耗资源

使用场景

读多写少的场景下,更新时很少发生冲突,使用乐观锁,减少了上锁和释放锁的开销,可以有效地提升系统的性能。

相反,在写多读少的场景下,如果使用乐观锁会导致更新时经常产生冲突,然后线程会循环重试,这样会增大CPU的消耗。在这种情况下,建议可以使用悲观锁

总结

在日常的开发中,悲观锁和乐观锁应该是见得最多,用得最多的锁,比如最常见的synchronizedReentrantLock是悲观锁,并发包中的原子类和ConcurrentHashMap则用了乐观锁。锁的实现并不复杂,关键是搞懂这两种锁的思想,这样才能在合适的地方使用合适的锁。

这篇文章就讲到这里了,希望看完后能有所收获,感谢你的阅读。

觉得有用就点个赞吧,你的点赞是我创作的最大动力~

我是一个努力让大家记住的程序员。我们下期再见!!!

能力有限,如果有什么错误或者不当之处,请大家批评指正,一起学习交流!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/488938.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

oracle session_wait,转载:学习Oracle动态性能表-(8)-V$SESSION_WAIT,V$SESSION_EVENT

(1)-V$SESSION_WAIT这是一个寻找性能瓶颈的关键视图。它提供了任何情况下session在数据库中当前正在等待什么(如果session当前什么也没在做,则显示它最后的等待事件)。当系统存在性能问题时,本视图可以做为一个起点指明探寻问题的方向。V$SESSION_WAIT中…

为了研究因果关系,原来科学家在这么多方向上都有尝试

来源:混沌巡洋舰1. 为何关注因果关系在现代科学之前,不管东西方,都是从经验出发,通过归纳获得知识,然而这样的知识,受限于观测,无法产生突破性的成果,在这样的模式下,再探…

[leetcode sort]56. Merge Intervals

Given a collection of intervals, merge all overlapping intervals. For example,Given [1,3],[2,6],[8,10],[15,18],return [1,6],[8,10],[15,18]. 合并重叠区间 1 class Solution(object):2 def merge(self, intervals):3 """4 :type i…

oracle solaris 内核 源码,直接安装内核区域

直接安装内核区域直接安装是缺省的内核区域安装方法。在直接安装中,安装程序将在全局区域中运行。缺省情况下,安装程序将创建和格式化内核区域引导磁盘,并使用全局区域的 pkg 发布者在该磁盘上安装 Oracle Solaris 软件包。注 -在内核区域直接…

mysql 有一组经纬度 返回在某个区域内_Qt编写地图综合应用17-地址经纬度互转

## 一、前言地址和经纬度互相转换的功能也经常用到,比如上次的路线方案查询的功能,之前官网是提供了直接输入出发地点和目的地的中文汉字,就可以查询到最优的路线,后面只支持输入出发地点和目的地的经纬度坐标了,这个就…

杨强 : 迁移学习——人工智能的最后一公里

来源:智能系统学报11月30日上午,第九届吴文俊人工智能科学技术奖颁奖典礼暨2019中国人工智能产业年会在苏州广电大厦演播厅隆重举行。本届大会主题是“突破关键技术赋能产业落地”。大会邀请到国家部委专家、两院院士和产业领军人士,围绕77场…

《Spring》(十六)---- JDBC

一般情况下&#xff0c;都是在DAO类中使用JdbcTemplate&#xff0c;JdbcTemplate在XML配置文件中配置好&#xff0c;直接在DAO中注入即可。 <?xml version"1.0" encoding"UTF-8"?> <beans xmlns"http://www.springframework.org/schema/be…

直接点oracle表编辑器,DbForge Studio for Oracle入门教程:如何在表编辑器中创建表...

dbForge Studio for Oracle是一个功能强大的集成开发环境(IDE)&#xff0c;它提供了通用的数据编辑工具来管理数据库内和外部数据&#xff0c;能够帮助Oracle开发者提高PL/SQL的编码速度。【dbForge Studio for Oracle 最新试用版下载】在本文示例中&#xff0c;我们将创建一个…

设置窗口置顶_这三个应用,每一个都能让你置顶。

| 当你有多个窗口同时打开&#xff0c;置顶其中某个或某些&#xff0c;能够方便你对比、学习、抄写……但不是所有软件都有这个功能&#xff0c;所以你需要今天的小干货。|-----------你的高效生活视频书。将窗口置顶&#xff0c;可以方便我们对比、写作、修改文案或代码&#…

汽车传感器科普

来源&#xff1a;湖杉资本先进驾驶辅助系统&#xff08;Advanced Driver Assistant System&#xff09;&#xff0c;简称ADAS&#xff0c;是利用安装于车上的各式各样的传感器&#xff0c; 在第一时间收集车内外的环境数据&#xff0c; 进行静、动态物体的辨识、侦测与追踪等技…

人工智能的现状与未来

来源&#xff1a; CIO之家几十年来计算速度飞速提高&#xff0c;从最初的科学数学计算演变到了现代的各种计算机应用领域&#xff0c;诸如多媒体应用&#xff0c;计算机辅助设计&#xff0c;数据库&#xff0c;数据通信&#xff0c;自动控制等等&#xff0c;人工智能是计算机科…

php分页技术的作用,分页原理技术细节剖析(php+mysql)实例

提到分页&#xff0c;大家都不陌生&#xff0c;在我们日常浏览网页时常遇到&#xff0c;尤其新闻文章列表等都有分页&#xff0c;如下图所示&#xff1a;分页实例下面&#xff0c;通过一个实例为大家剖析一下分页原理上技术细节。一、功能开发思路在分页功能的实现前&#xff0…

python idle 中文_Python IDLE 中文乱码问题

最近忙完了一个比较大的 GIS 软件系统&#xff0c;于是闲暇之余想研究一下开源的技术&#xff0c;纵观当前开源桌面 GIS 软件领域&#xff0c;最牛叉的莫过于大名鼎鼎的 Quantum GIS&#xff0c;简称 QGIS。做过 GIS 的人都知道&#xff0c;ESRI ArcGIS 是 GIS 软件领域迄今为止…

常见浏览器兼容性问题及解决方案

常见浏览器兼容性问题及解决方案&#xff1a; 1.不同浏览器的默认内外边距和内外补丁不同。 解决方案&#xff1a;css设置 *{margin:0; padding:0;} *是通配符&#xff0c;匹配所有html标签。 2.块级元素float之后&#xff0c;又有横向margin时&#xff0c;IE6显示margin比设置…

2020年物联网发展现状与趋势预测

来源&#xff1a;北京物联网智能技术应用协会一、综述物联网源于互联网领域&#xff0c;是信息科学技术产业的第三次革命。物联网是基于互联网&#xff0c;让所有物体能够独立寻址的普通物理对象实现互联互通的网络。简单说&#xff0c;就是通过安装信息传感设备&#xff0c;如…

shell中执行某条语句失败能不能重复执行_如何理解Mysql中的事务隔离级别?

要说清楚Mysql中的事务隔离级别&#xff0c;我们先从事务的定义说起。事务&#xff0c;是一个或一组sql语句组成的一个执行单元&#xff0c;这个执行单元要么全部执行&#xff0c;要么全部不执行。整个单独单元作为一个不可分割的整体&#xff0c;如果单元中某条sql语句一旦执行…

oracle 试图访问已经在使用的事物处理临时表,解决ORA-14450:试图访问已经在使用的事务处理临时表...

在开发使用过程中&#xff0c;一个存储过程用到表TMP_DA_GMS,允许程序的时候报错&#xff0c;后台查询到错误原因是因为表里有个字段需要设置为可以为N在开发使用过程中&#xff0c;一个存储过程用到表TMP_DA_GMS,允许程序的时候报错&#xff0c;后台查询到错误原因是因为表里有…

linux 下环境变量设置

Ubuntu Linux系统包含两类环境变量&#xff1a;系统环境变量和用户环境变量。系统环境变量对所有系统用户都有效&#xff0c;用户环境变量仅仅对当前的用户有效。 修改用户环境变量 用户环境变量通常被存储在下面的文件中&#xff1a; ~/.profile ~/.bash_profile 或者 ~./bas…

《数字孪生体技术白皮书(2019)》(简版)全文

来源&#xff1a;《数字孪生体实验室原创》12月27日&#xff0c;数字孪生体实验室与安世亚太联合正式发布了《数字孪生体技术白皮书&#xff08;2019&#xff09;》。白皮书的第一部分关注对数字孪生体的抽象和总结。无论是参考架构、成熟度模型还是关键技术&#xff0c;都以“…

oracle批量构造数据,oracle批量构造数据方法 - rd_clp的个人空间 - 51Testing软件测试网 51Testing软件测试网-软件测试人的精神家园...

1.一种是只要数据条数&#xff0c;至于里面内容可以是序列方式&#xff0c;另外可能几个表中相互id的关联&#xff0c;那建议用存诸过程写.表a(id,name)有学员的信息表b(id,testid,subject,score)有学员的考试成绩假设表a与表b的id都是有seq的自增长系列&#xff1b;表b.testid…