本文共 1126 字,大约阅读时间需要 3 分钟。
在操作时持乐观态度,认为操作时其它线程不会修改数据,因此不会锁定数据,但是在更新数据时会用版本号或者CAS算法判断数据在本次操作过程中是否被更改,如果被更改,则修改失败。
所以乐观锁虽然名字带锁,但是实际上并不会对数据进行锁定操作,其它线程仍然可以自由地读写数据,不会造成死锁等问题。
乐观锁不会锁定数据,所以其它需要读取数据的线程不需要等待,但是如果更新频繁,频繁地出现修改失败回滚的情况,反而会导致性能及使用体验的问题。
因此乐观锁适用于需要频繁读取数据,但是较少更新数据的场景。
Java中原子变量使用了CAS算法来避免加锁,同时保证数据修改的正确性:
使用volatile声明该变量为线程间共享变量;
使用CAS算法保证变量修改的正确性,我们可以调用compareAndSet函数来尝试修改原子变量,该函数会返回修改的结果,如果成功,则操作完成,如果失败则获取新值处理后继续尝试;
乐观锁通常有两种实现方式:
通过版本号机制实现;
通过CAS(compare and swap)算法实现;
CAS是compare and swap的缩写,算法逻辑就是当一个线程要修改某个数据时,需要携带上之前的原数据,服务端会将这个原数据与当前数据进行比对,如果一致,则将当前数据替换为申请修改的数据,如果不一致,则修改失败。
在大多数情况下,这都是没有问题的,但如果我们需要严格保证原数据未经变动时,则可能出现问题,相比较使用版本号实现的乐观锁则可以避免此问题。
在操作时持悲观态度,认为其它线程会修改数据,所以更新数据时对数据进行锁定,加锁后,同一时间只能有一个线程执行,其它线程只能等待直到锁被其它线程释放。
悲观锁可以保证数据操作时的正确性,不会出现数据因被其它线程修改而失败的情况,但是它会限制其它线程读取数据。
所以悲观锁更适用于修改频繁,使用乐观锁会频繁冲突回滚,但读取较少的场景。
Java的synchronized关键字就是一种悲观锁
《》
《》
转载地址:http://rptlf.baihongyu.com/