zoukankan      html  css  js  c++  java
  • 常用到的多种锁(随时可能修改)


    在Java内存模型中,有main memory,每个线程也有自己的memory (例如寄存器)。为了性能,一个线程会在自己的memory中保持要访问的变量的副本。这样就会出现同一个变量在某个瞬间,在一个线程的memory中的值可能与另外一个线程memory中的值,或者main memory中的值不一致的情况。 

     
    violate 并不是锁,只是规定该变量不允许使用备份(缓存),只能从内存读写,但这并不说是线程安全的。
     

    原因:Volatile一般情况下不能代替sychronized,因为volatile不能保证操作的原子性,即使只是i++,实际上也是由多个原子操作组成:read i; inc; write i,假如多个线程同时执行i++,volatile只能保证他们操作的i是同一块内存,但依然可能出现写入脏数据的情况。如果配合Java 5增加的atomic wrapper classes,对它们的increase之类的操作就不需要sychronized。 

     

    广义重入锁  递归调用的时候,同一线程能不能再次获得锁 

     
    ReentrantLock 
     
        - 没有线程持有锁的时候,state为0。
        - 当某个线程获取锁时,state的值增加,具体增加多少开发人员可自定义,默认为1,表示该锁正在被一个线程占有。
        - 当某个已经占用锁的线程再次获取到锁时,state再增长,此为重入锁。
        - 当占有锁的线程释放锁时,state也要减去当初占有时传入的值,默认为1。
     
     
     
    数据库悲观锁
     
    update 或者手动获取锁(for update)
     
    索引列是锁索引筛选到的列(无需全表扫描)
     
    其他列锁表(全表扫描)
     
    (多个查询条件也不影响上面的逻辑,所以库存扣减完全可以限制id+库存>0 来update获取行数)
     
    乐观锁
     

    需要自己实现,常用做法是记录一个递增的version,提交时候验证

     
    Redis实现分布式锁
     

    利用setIf来实现,网上提供的例子中,锁不能保证公平性,而且自定义的sleep容易导致线程堵死,加超时时间又和业务违背(请求失败)

    目前没有发现好的策略
     
    Zookeeper分布式锁
     

    利用临时自增节点的特性,观察某个节点,然后每次有变化查看自己是不是最小的,如果是最小的,那么执行,不是最小的,继续等待。

    这个性能上待测试

    看到有错,麻烦指出谢谢!

  • 相关阅读:
    Sum Root to Leaf Numbers 解答
    459. Repeated Substring Pattern
    71. Simplify Path
    89. Gray Code
    73. Set Matrix Zeroes
    297. Serialize and Deserialize Binary Tree
    449. Serialize and Deserialize BST
    451. Sort Characters By Frequency
    165. Compare Version Numbers
    447. Number of Boomerangs
  • 原文地址:https://www.cnblogs.com/luochengqiuse/p/4921247.html
Copyright © 2011-2022 走看看