zoukankan      html  css  js  c++  java
  • 并发编程--乐观锁与悲观锁

    1. 什么是乐观锁、悲观锁

    乐观锁:总是认为会是最好的情况,每次去取数据都认为别人不会修改,所以不会上锁,但是去更新的时候会判断在这期间有没有人对这个值进行修改,一般使用version机制CAS算法来实现;乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库提供的类似于write_condition机制,其实都是提供的乐观锁。在Java中java.util.concurrent.atomic包下面的原子变量类就是使用了乐观锁的一种实现方式CAS实现的。

    悲观锁:总是认为会是最坏的情况,每次去取数据都认为别人会修改,所以每次取数据的时候都会上锁,别人取数据就会阻塞,直到它将这个锁释放掉,拿到锁才能取到数据;一般多写的场景下用悲观锁就比较合适,传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。Java中synchronizedReentrantLock等独占锁就是悲观锁思想的实现。

    2. 乐观锁的两种实现方式

    2.1 version版本号机制

    一般是在数据库表中加上一个版本号的字段version,该字段表示数据被修改的次数,数据每次进行修改时,都会进行version+1,当某个线程要更新数据时,会在读取数据的同时也读取到version值,然后提交更新时,会将获取到的version值与此时数据库中的值进行比较,如果相等进行更新,否则重试更新操作,直到更新成功

    2.2 CAS无锁算法

    即compare and swap(比较和交换),该算法主要涉及三个操作数:

    需要读写的内存值 V

    进行比较的值           A

    拟写入的新值      B

    只有当V=A时,通过原子的方式用B值更新V的值,否则不会进行任何操作。一般情况下是一个自旋操作,即不断的重试。

    3. 乐观锁的缺点

    1)ABA问题:如果线程1获取到变量的值为A,然后在线程1执行更新操作之前的这段时间里,线程2将这个变量的值先改成了B,然后又改回了A,此时线程1再去进行比较,会发现值是相等的,所以会认为在这期间该值没有被修改过.

    2)循环时间开销大:前面说过如果失败会一直重试更新操作,知道成功为止,如果一直不成功,会给CPU带来非常大的执行开销

  • 相关阅读:
    笔记-归并排序
    Repeated Substring Pattern
    Assign Cookies
    Number of Boomerangs
    Paint Fence
    Path Sum III
    Valid Word Square
    Sum of Two Integers
    Find All Numbers Disappeared in an Array
    First Unique Character in a String
  • 原文地址:https://www.cnblogs.com/Cryptonym/p/10675529.html
Copyright © 2011-2022 走看看