首页 > 其他分享 >CAS与乐观锁

CAS与乐观锁

时间:2023-02-12 19:56:14浏览次数:38  
标签:CAS 更新 版本号 乐观 修改 线程 数据

1 什么是乐观锁?

说到乐观锁,就不得不先提起悲观锁(Pessimistic Lock),或者说是悲观并发控制(Pessimistic Concurrency Control,PCC)。悲观锁认为多线程同时修改共享资源的概率比较高,于是很容易出现冲突,所以访问共享资源前,先要上锁。而乐观版本控制(Optimistic Concurrency Control,OCC)与之相反,认为多线程同时修改共享资源的概率低,因此在访问共享资源前并不加锁,而是在更新数据时验证操作时间内有没有发生冲突,如果没有其他线程在修改资源,那么操作完成,如果发现有其他线程已经修改过这个资源,就放弃本次操作。

2 如何实现乐观锁?

实现乐观锁的方式有CAS和版本号机制

2.1 compare-and-swap(CAS)

CAS是一种原子操作,在对一个数据进行更新前,需要先持有这个数据原有值的备份,在进行更新前CAS会比较该数据当前值与备份值是否相同,如果不同则认为被更改,放弃对数据的更新。由于是原子操作,如果有多个线程同时修改一个数据,将会只有一个线程成功。(原子操作通过总线仲裁机制/MESI协议等保证)
CAS过程可以用以下C代码表示:

int cas(long *addr, long old, long new) 
{
    /* Executes atomically. */
    if(*addr != old)
        return 0;
    *addr = new;
    return 1;
}

ABA问题

ABA问题是无锁结构实现中的常见问题,试想两个线程基于cas访问变量A,线程1读取A的值后被挂起,线程2修改A为数值B又改回了A,之后线程1被唤醒,CAS的条件仍然满足,线程1修改了A的变量继续运行。如果只需要考虑开头和结尾一致,这个问题并不重要。
在CAS操作中,由于比较的多是指针,这个问题将会变得更加严重。详见:https://zh.wikipedia.org/zh-hans/比较并交换

2.2 版本号方式

简单来说就是给线程访问的数据增加一个版本标识,可以是版本号也可以是时间戳,当读取数据时将版本号一同读出作为备份,在更新数据之前检查版本号是否和备份相同,如果相同则更新数据,如果不同则认为中间有修改放弃更新。

标签:CAS,更新,版本号,乐观,修改,线程,数据
From: https://www.cnblogs.com/Big-xu/p/17114557.html

相关文章

  • 【论文阅读】DSTAGNN Dynamic Spatial-Temporal Aware Graph Neural Network for Traf
    DSTAGNNDynamicSpatial-TemporalAwareGraphNeuralNetworkforTrafficFlowForecastingInfotitle:DSTAGNN:DynamicSpatial-TemporalAwareGraphNeuralNetw......
  • CAS 悲观锁 乐观锁
    前面的偏向锁,轻量级锁,重量级锁都是悲观锁,都会认为必须要对操作对象进行互斥访问,不然就会产生异常,所以线程只供一个线程使用,阻塞其他线程,是悲观的在某些情况下,同步的耗时......
  • 悲观锁和乐观锁
    悲观锁:认为线程问题一定会发生,在操作数据之前就获取锁,确保线程串行执行。列如Synchronized、lock乐观锁:认为线程问题不一定发生,因此不加锁,只是在更新数据时去判断有没有其......
  • Kubernetes(k8s)控制器(四):ReplicaSet
    目录一.系统环境二.前言三.ReplicaSet概览四.ReplicaSet工作原理五.ReplicaSet使用场景六.创建ReplicaSet七.扩展replicaset副本数一.系统环境服务器版本docker软件......
  • [蓝桥杯 2019 省 A] 组合数问题-Lucas定理、数位dp
    洛谷的题目链接:https://www.luogu.com.cn/problem/P8688Lucas定理,把\(k|binom{i}{j}\)转换成在k进制下存在某个数位i比j小,再转换成反面计算每一位i都比j大,然后就是经典......
  • switch case多选择结构/查看反编译类文件
    switchcase多选择结构switch中变量类型可以是byte,short,int或char,从javaSE7开始,switch支持字符串类型。publicclassdemo09{publicstaticvoidmain(String[]......
  • SpringBoot工程入门case
    SpringBoot的设计目的是用来简化Spring应用的初始搭建以及开发过程。SpringBoot入门案例:1、创建一个新module  2、除pom和src文件剩余都删除。  3、在src.com......
  • ICMPv6 Multicast Listener Report Message v2
    No.TimeSourceDestinationProtocolInfo70.164795fe80::f8ae:aae:ee9a:bdc0ff02::16ICMPv6MulticastListenerReportMessagev2Frame......
  • C语言填空:周几判断 switch case应用
    /*假设今天是星期日,编写一个程序,求123456天后是星期几*/#include<stdio.h>intmain(){intn,iday;printf("请输入天数:");scanf("%d",【1】);【2】;switch(【3】)......
  • C语言填空:switch case练习
    /*下列程序的功能为:实现加、减、乘、除四则运算。*///【1】【2】【3】【4】【5】【6】【7】【8】【9】【10】#include<stdio.h>voidmain(){inta,b,d;......