MySQL乐观锁(MySQL乐观锁)

悲观锁与乐观锁的区别悲观锁会把整个对象加锁占为已有后才去做操作,Java中的Synchronized属于悲观锁。悲观锁有一个明显的缺点就是:它不管数据存不存在竞争都加锁,随着并发量增加,且如果锁的时间比较长,其性能开销将会变得很大。乐观锁不获取锁直接做操作,然后通过一定检测手段决定是否更新数据,这种方式下,已经没有所谓的锁概念了,每条线程都直接先去执行操作,计算完成后检测是否与其他线程存在共享数据…

大家好,又见面了,我是你们的朋友全栈君。

悲观锁与乐观锁的区别

悲观锁会把整个对象加锁占为已有后才去做操作,Java中的Synchronized属于悲观锁。悲观锁有一个明显的缺点就是:它不管数据存不存在竞争都加锁,随着并发量增加,且如果锁的时间比较长,其性能开销将会变得很大。

乐观锁不获取锁直接做操作,然后通过一定检测手段决定是否更新数据,这种方式下,已经没有所谓的锁概念了,每条线程都直接先去执行操作,计算完成后检测是否与其他线程存在共享数据竞争,如果没有则让此操作成功,如果存在共享数据竞争则可能不断地重新执行操作和检测,直到成功为止。

CAS算法

乐观锁的核心算法是CAS(Compareand Swap,比较并交换),它涉及到三个操作数:内存值、预期值、新值,当且仅当预期值和内存值相等时才将内存值修改为新值。这样处理的逻辑是,首先检查某块内存的值是否跟之前我读取时的一样,如不一样则表示期间此内存值已经被别的线程更改过,舍弃本次操作,否则说明期间没有其他线程对此内存值操作,可以把新值设置给此块内存。

假如你足够细心你可能会发现一个疑问,比较和交换,从字面上就有两个操作了,更别说实际CAS可能会有更多的执行指令,他们是原子性的吗?如果非原子性又怎么保证CAS操作期间出现并发带来的问题?我是不是需要用上节提到的互斥锁来保证他的原子性操作?CAS肯定是具有原子性的,不然就谈不上在并发中使用了,但这个原子性是由CPU硬件指令实现保证的,即使用JNI调用native方法调用由C++编写的硬件级别指令,jdk中提供了Unsafe类执行这些操作。另外,你可能想着CAS是通过互斥锁来实现原子性的,这样确实能实现,但用这种方式来保证原子性显示毫无意义。下面一个伪代码加深对CAS的理解:

public class AtomicInt {

private volatile int value;

public final int get() {

return value;

}

publicfinal int getAndIncrement() {

for (;;) {

int current = get();

int next = current + 1;

if (compareAndSet(current, next))

return current;

}

}

public final boolean compareAndSet(int expect, int update) {

//Unsafe类提供的硬件级别的compareAndSwapInt方法;

}

}

其中最重要的方法是getAndIncrement方法,它里面实现了基于CAS的自旋。

乐观锁的缺点

现在已经了解乐观锁及CAS相关机制,乐观锁避免了悲观锁独占对象的现象,同时也提高了并发性能,但它也有缺点:

观锁只能保证一个共享变量的原子操作。如上例子,自旋过程中只能保证value变量的原子性,这时如果多一个或几个变量,乐观锁将变得力不从心,但互斥锁能轻易解决,不管对象数量多少及对象颗粒度大小。

长时间自旋可能导致开销大。假如CAS长时间不成功而一直自旋,会给CPU带来很大的开销。

ABA问题。CAS的核心思想是通过比对内存值与预期值是否一样而判断内存值是否被改过,但这个判断逻辑不严谨,假如内存值原来是A,后来被一条线程改为B,最后又被改成了A,则CAS认为此内存值并没有发生改变,但实际上是有被其他线程改过的,这种情况对依赖过程值的情景的运算结果影响很大。解决的思路是引入版本号,每次变量更新都把版本号加一。

乐观锁是对悲观锁的改进,虽然它也有缺点,但它确实已经成为提高并发性能的主要手段,而且jdk中的并发包也大量使用基于CAS的乐观锁。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/127513.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 爱玩吧提供10G国外免费PHP空间「建议收藏」

    爱玩吧提供10G国外免费PHP空间「建议收藏」爱玩吧提供10G国外免费PHP空间爱玩吧香港空间:不再开放免费空间申请。大家就去用免费国外不限制空间申请Yhfx.ml免费空间服务由idc.aiwanba.net提供 免费空间套餐每月流量 100GB空间容量10GB控制面板演示

  • IsoAlgo3d – A PCF 3D Viewer for Desktop, Tablet and Smart phone

    IsoAlgo3d – A PCF 3D Viewer for Desktop, Tablet and Smart phone

  • burpsuite小米手机抓包_Android 7.0+手机burpsuite抓包https

    burpsuite小米手机抓包_Android 7.0+手机burpsuite抓包https记录一下以后可能会遇到的此类问题的解决方案。方法1:系统证书目录:/system/etc/security/cacerts/其中的每个证书的命名规则如下:.文件名是一个Hash值,而后缀是一个数字。文件名可以用下面的命令计算出来:opensslx509-subject_hash_old-in后缀名的数字是为了防止文件名冲突的,比如如果两个证书算出的Hash值是一样的话,那么一个证书的后缀名…

  • 熊猫烧香病毒简析[通俗易懂]

    熊猫烧香病毒简析[通俗易懂]熊猫烧香从2007年1月肆虐网络到现在。已经过了查不多4个年头了。病毒的作者李俊现在也从监狱里被放了出来。在当时熊猫烧香确实给大家一个意外,它采用了一种新的方式对计算机的程序和系统造成了很严重的破坏。 其实我的这篇文章也不叫什么分析,只是说简单的简析。我只是简单的对病毒的机

    2022年10月28日
  • cstring头文件都有什么函数_cstdlib是什么头文件

    cstring头文件都有什么函数_cstdlib是什么头文件cstring中包含许多字符数组的函数:strlen()函数:strlen函数可以得到字符数组中第一个\0前的字符的个数strcmp()函数:strcmp函数返回两个字符串大小的比较结果,比较原则是按字典序strcpy()函数:strcpy函数可以把一个字符串复制给另一个字符串strcat()函数:strcat()可以把一个字符串接到另一个字符串后面sscanf与sprintf用法:假设定义了一个字符数组str[100],如下:sscanf(str,”%d”,

  • c语言二维数组传参数_c语言数组传参

    c语言二维数组传参数_c语言数组传参初遇二维数组作函数参数,宛如自己化身为了大头儿子。很头大。不禁大声呐喊:该怎么声明定义,该怎么调用,又该怎么函数中操作元素和地址?在此,我要拨开这些问题的一些迷雾。我相信,有心人看完后,再遇就不会怕了。其实声明,定义是一样的。因此,只写声明。同时,把元素外层*()剥去就代表地址。因此只写元素。最后有总结。二维数组作函数参数,依我看来,至少可以分成三种。事先,在main函数中int…

    2022年10月31日

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号