zoukankan      html  css  js  c++  java
  • 概念-乐观锁、悲观锁

    听到 乐观锁、悲观锁的概念,搜了下,摘要出为能理解的尽量短的文字说明:

    概念

    悲观锁:正常的经典使用方式是叫悲观锁,先取锁,成功取得后才做操作(不论是读还是写)。

    乐观锁:乐观并发控制相信事务之间的数据竞争(data race)的概率是比较小的,因此尽可能直接做下去,直到提交的时候才去锁定,所以不会产生任何锁和死锁。

    其他说明

    乐观锁,提交的时候,如果冲突,则返回给用户异常信息,让用户决定如何去做。

    悲观锁主要分为共享锁 和排他锁

    • 共享锁【shared locks】又称为读锁,简称 S 锁。顾名思义,共享锁就是多个事务对于同一数据可以共享一把锁,都能访问到数据,但是只能读不能修改。
    • 排他锁【exclusive locks】又称为写锁,简称 X 锁。顾名思义,排他锁就是不能与其他锁并存,如果一个事务获取了一个数据行的排他锁,其他事务就不能再获取该行的其他锁,包括共享锁和排他锁。获取排他锁的事务可以对数据行读取和修改。

    这么看自己实际使用的时候,普通的锁,内部应该就是个排他锁;而读写锁似乎内部一个排他锁和一个共享锁组成,读的加锁和解锁过程应该是用了内部共享锁,写的加锁和解锁则应该是用了内部的排他锁。

    怀疑似乎这概念应该是 从java的 CAS  包的实现传播开的

    扩展

    简单搜了下 CAS的概念,即compare and swap(比较与交换),是一种有名的无锁算法。瞄了眼,似乎是有一套理论来说明它的实现和优缺点。

    了解cas时,自然的也会涉及到个 自旋锁的概念。下面说的是我的理解,没找到这个概念的最初出处,并不确信也未做验证。

    自旋锁似乎是说的取锁的方式,普通的加锁(或者说尝试取锁)时,如果没获取成功,加锁函数可能会让自己卡在调用函数处;而自旋锁的方式是尝试获取,如果不成功立刻进行下一次获取尝试,一直死循环到获取成功。

    这里说的卡住,应该是让渡出当前的线程调度,系统会挂起(或其他操作)当前线程,改去执行其他线程。

    而自旋锁的死循环获取方式则是不会主动让渡。

    当然系统的调度cpu分配规则,或许也会因为时间片到了而阻塞自旋锁的线程,但这对于普通加锁方式的线程应该也是一样没差别的。

    每次cpu重新调度到当前线程的时候,执行代码依次还是沿用各自的方式,

    如果普通取锁方式,出现了等待,是否是注册了下,等到资源释放了才会通知改变该线程的状态,不通知期间系统不再会调度该线程(给它分配时间片)?

    非自旋的获取会有内核模式切换的代价。为什么有这个代价,是那个获取锁的函数本身就是个系统调用造成的,还是获取失败的情况下会产生中断,让出执行权限造成的?目前不太确定。

    如果说自旋锁没有内核模式切换的代价。那也就是说,它那尝试的操作(那个函数调用)判断,肯定不是个系统调用。

    普通锁和自旋锁分别对应概念:mutex和spin lock 及 sleep-waiting和busy-waiting的区别

    参考

    主要参考摘录自:

    https://www.jianshu.com/p/d2ac26ca6525

    https://www.cnblogs.com/wangshaowei/p/14358774.html

  • 相关阅读:
    nodejs设置NODE_ENV环境变量(2)
    CentOS6.8系统安装Node
    mongodb3.X权限配置
    在centos7中添加一个新用户并授权
    CentOS 7.0启用iptables防火墙
    Nginx编译参数大全 configure参数中文详解
    Linux(centos)系统各个目录的作用详解
    CentOS 6.5_X64下安装MongoDB数据库
    vue-cli 发布(译)
    Linux下的crontab定时执行任务命令详解
  • 原文地址:https://www.cnblogs.com/xiarl/p/14852759.html
Copyright © 2011-2022 走看看