zoukankan      html  css  js  c++  java
  • 乐观锁和悲观锁的理解及如何实现,有哪些实现方式?

    悲观锁:总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每

    次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁。传

    统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写

    锁等,都是在做操作之前先上锁。再比如 Java 里面的同步原语 synchronized 关

    键字的实现也是悲观锁。

    乐观锁:顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所

    以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,

    可以使用版本号等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量,

    像数据库提供的类似于 write_condition 机制,其实都是提供的乐观锁。在 Java

    java.util.concurrent.atomic 包下面的原子变量类就是使用了乐观锁的一种实

    现方式 CAS 实现的。

    乐观锁的实现方式

    1、使用版本标识来确定读到的数据与提交时的数据是否一致。提交后修改版本标

    识,不一致时可以采取丢弃和再次尝试的策略。

    2、java 中的 Compare and Swap 即 CAS ,当多个线程尝试使用 CAS 同时更新

    同一个变量时,只有其中一个线程能更新变量的值,而其它线程都失败,失败的

    线程并不会被挂起,而是被告知这次竞争中失败,并可以再次尝试。 CAS 操作

    中包含三个操作数 —— 需要读写的内存位置(V)、进行比较的预期原值(A)

    和拟写入的新值(B)。如果内存位置 V 的值与预期原值 A 相匹配,那么处理器会自

    动将该位置值更新为新值 B。否则处理器不做任何操作。

    CAS 缺点

    1、ABA 问题

    比如说一个线程 one 从内存位置 V 中取出 A,这时候另一个线程 two 也从内存中

    取出 A,并且 two 进行了一些操作变成了 B,然后 two 又将 V 位置的数据变成 A,

    这时候线程 one 进行 CAS 操作发现内存中仍然是 A,然后 one 操作成功。尽管线

    one 的 CAS 操作成功,但可能存在潜藏的问题。从 Java1.5 开始 JDK 的 atomic

    包里提供了一个类 AtomicStampedReference 来解决 ABA 问题。

    2、循环时间长开销大

    对于资源竞争严重(线程冲突严重)的情况,CAS 自旋的概率会比较大,从而浪

    费更多的 CPU 资源,效率低于 synchronized。

    3、只能保证一个共享变量的原子操作

    当对一个共享变量执行操作时,我们可以使用循环 CAS 的方式来保证原子操作,

    但是对多个共享变量操作时,循环 CAS 就无法保证操作的原子性,这个时候就可

    以用锁。

  • 相关阅读:
    泛微云桥e-Bridge 目录遍历,任意文件读取
    (CVE-2020-8209)XenMobile-控制台存在任意文件读取漏洞
    selenium 使用初
    将HTML文件转换为MD文件
    Python对word文档进行操作
    使用java安装jar包出错,提示不是有效的JDK java主目录
    Windows server 2012安装VM tools异常解决办法
    ifconfig 命令,改变主机名,改DNS hosts、关闭selinux firewalld netfilter 、防火墙iptables规则
    iostat iotop 查看硬盘的读写、 free 查看内存的命令 、netstat 命令查看网络、tcpdump 命令
    使用w uptime vmstat top sar nload 等命令查看系统负载
  • 原文地址:https://www.cnblogs.com/programb/p/13021132.html
Copyright © 2011-2022 走看看