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是我们从数据库表中获取的,具有实时性。

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

原文地址:https://www.cnblogs.com/pogusanqian/p/12992985.html