Java 乐观锁和悲观锁

前言

  在说乐观锁和悲观锁之前,先说一下什么是锁,为什么要用到锁?
  在实际生活中,有很多地方用到了锁,例如:家门上的指纹锁、保险柜上的密码锁和登录微信时的账号密码等等。这些锁保证了我们的人身安全、财富安全和个人信息安全。
  而程序中的锁则是保证了数据安全。当有多个线程去访问共享数据的时候,我们可以给数据加上锁,保证了数据的(syncronized)。当多个用户去修改用一个数据的时候,给数据加上锁,可以处理一部分并发问题,保证数据被修改后呈现的效果跟一个用户修改数据后呈现的效果一致。



  上图所示,有两个用户同时访问数据库更新数据,数据最终的数据可能是3也可能是5,导致数据的不准确。

乐观锁

  乐观锁,就像是生活中很乐观的人。举个例子:有一个公共厕所,乐观的人去上厕所,会认为厕所有人,别人就不会进来,所以就不锁门直接上,因为锁门开门很浪费时间。在代码中,乐观锁在读数据的数据的时候是没有给数据上锁的,所有用户可以随便的去读数据。但是在修改数据的时候就需要去看看有没有人正在修改,或者已经是修改后了的数据。



乐观锁可以利用版本号机制和CAS算法实现。

版本号机制

  版本号机制是给表加上一个version字段


具体的实现流程:

  1. 用户A和用户B同时去查询水杯的剩余数量,查询到数据inventory_quantity = 1version = 1
  2. 用户A带着version = 1的条件更新,水杯的库存数量-1并将版本号+1,更新成功,接口返回正确的信息。
  3. 用户B带着version = 1的条件更新,更新完后发现受影响行数为0,更新失败,接口返回错误或者其他的信息。

CAS

说到乐观锁,就必须提到CAS机制。什么是CAS机制?
CAS全称,Compare-And-Set,比较并设置。
比较:比较获取到一个值A,再把它更新成B的同时判断该值是否还为A。
设置:如果是,更新为B,如果不是,回滚重试。
  这两步对CPU来说是瞬间完成的。有了CAS就可以实现乐观锁,因为没有就加锁的步骤,所以可以多个线程同时读取,并且只有一个线程可以访问成功。因为乐观锁没有“加锁”和“解锁”的过程,所以也被称为“无锁编程”。
但CAS有一个新的问题,就是ABA问题。

ABA

什么是ABA问题。
  一个线程在获取到某个变量的时候值为A,但无法确定这个变量是否被别的线程修改过。其他的线程可以先把值改为B,在做完操作后又把值改为A。
  解决办法就是,给表加一个version字段,操作完数据之后把version字段+1,当然线程在查数据的时候也需要查version字段,并且在做更新的时候判断version字段是否为1

悲观锁

  悲观锁,就像是生活中很悲观的人。举个例子:假设厕所只有一个坑位,悲观的人在上厕所的时候会把门锁住,这样别人就进不来了。在代码中,给一个共享数据加上悲观锁,那么当一个线程访问到了数据后,会假设别的线程也会访问这个共享数据,就会给数据上锁,导致别的线程访问不到共享数据造成了阻塞。


悲观锁的实现


表结构如上,在不加锁的情况下,多名用户同时去购买会报错。悲观锁的实现是依靠数据库的锁机制:

  1. 当一个用户对水杯商品下单时,会先给该数据加上悲观锁。
  2. 加锁成功:此时水杯商品只能由加锁成功的用户操作,其他的用户再对水杯进行抢购的时候,发现数据被加上了悲观锁,只能等待开锁后再进行后续的操作。
  3. 加锁失败:说明该数据已经被其他用户加上了悲观锁,继续等待或者抛异常(根据实际情况定)。

    SQL语句这样写,先关闭mysql的自动提交属性,执行sqlset autocommit=0,然后再执行悲观锁加锁语句:select * from table where id = 1 for update。可以用两个窗口来进行测试。

两种锁的使用场景

  乐观锁回滚重试,悲观锁阻塞事务,没有孰好孰坏,两种锁的实现场景不一样。
  乐观锁适用于写少读多的场景,乐观锁本身没有加锁和解锁的操作,省去了锁的开销,从而提高了吞吐量。
  注意:乐观锁因为并未加锁,所以性能会很快,但是一旦锁的力度掌握不好,会导致更新失败,容易发生业务问题。
  悲观锁适用于写多的场景,如果线程竞争比较激烈,冲突比较严重,用乐观锁反而增加了线程重试的次数从而影响了性能。
  注意:悲观锁实现了“加锁”的操作,但是依赖于数据库,性能方面不如乐观锁。
点赞头上不掉发

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,384评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,845评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,148评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,640评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,731评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,712评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,703评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,473评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,915评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,227评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,384评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,063评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,706评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,302评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,531评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,321评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,248评论 2 352

推荐阅读更多精彩内容