zoukankan      html  css  js  c++  java
  • 207-乐观锁与悲观锁?

        首先我们应该明白锁可以我们写的程序上,也可以加载数据库上。但是数据库的行锁、表锁、读锁、都不是我们的事。
    我们所谓的加锁,都是加载我们的程序上的。
        悲观锁:认为我们的数据时刻都处于更改状态,所以只能又一个线程更改数据 。我们通过的synac(this)关键字给数据加锁。
        乐观锁:认为我们的数据大部分时刻都处于不变的状态,可以允许多个线程同时更改数据,但是通过了版本号进行了限制。

        乐观锁的本质方案:就是再数据库表中添加了一个版本号,如果数据库的版本号和我们更改前的版本号一致,就说明没有线程操作这张表,说明线程安全。乐观锁不是不让哪些线程进行执行,而是时哪些线程中的sql命令进行失效。

        悲观锁:悲观锁是不让其余线程执行。

        在这里其实我一直都有一个问题的,那就是获取数据库版本号的实时性是怎么体现的?
        查询表时,多个线程可以同时将表加载进内存,形成虚拟表。
        更改表时,只能由一个线程来操作数据库表。所以说10个线程不可能同时提交数据,只能一次进行提交。


        假如又10个线程同时操作数据库,这是个线程获取的版本号都是1,然后其中一个线程率先更改了数据库,讲版本号升级成了2,
        此时那9个线程是如何获取到版本号已经升级成了2呢?

        这里面应该牵扯到了数据库的值,注意我们这个时候不是查询操作,根本不用从硬盘中加载虚拟表到内存。
        update tbl_good set mount=mount-1 and version=version+1 where version == version and monut >= 0;

        不使用乐观锁,也不使用悲观锁,为什么会引发超卖现象呢?
        这是因为我们的十个线程即使不能同时提交,但是他们可以依次进行提交数据。反正这10个线程都被下达了操作数据库的命令。
        每个命令都会讲商品数量减一,这样便会引发超卖;

        不使用乐观锁也不使用悲观锁,为什么会出现覆盖的情况的?
        很简单,这十个数据再sql线程执行之前,获取的mount都是10,然后他们是给mount赋值的,mount=mount-1中后面的mount的值不具有实时性,是我们传递过来的。但是version == version中左面的version是我们从数据库表中获取的,具有实时性。

        可以说正是由于乐观锁的存在,我们才可以使用队列,如果使用悲观锁,我们就不能实行队列了。

  • 相关阅读:
    java 基本数据类型的取值范围
    警惕自增的陷阱
    三元操作符的类型务必一致
    不要随便设置随机种子
    优先使用整形池
    IN、ANY、ALL与SOME
    第六章-序列:字符串、列表和元组 笔记
    第十二章-安全性
    第五章-数字 课后答案
    第十一章-约束、视图与事务
  • 原文地址:https://www.cnblogs.com/pogusanqian/p/12992985.html
Copyright © 2011-2022 走看看