• 常用到的多种锁(随时可能修改)



    在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分布式锁
     

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

    这个性能上待测试

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

  • 相关阅读:
    [LeetCode] Range Sum Query
    [LeetCode] Additive Number
    [LeetCode] Number of Islands II
    [LeetCode] Range Sum Query 2D
    [LeetCode] Range Sum Query
    [LeetCode] Smallest Rectangle Enclosing Black Pixels
    [LeetCode] Longest Increasing Subsequence
    [LeetCode] Bulls and Cows
    [LeetCode] Binary Tree Longest Consecutive Sequence
    [LeetCode] Serialize and Deserialize Binary Tree
  • 原文地址:https://www.cnblogs.com/luochengqiuse/p/4921247.html
Copyright © 2020-2023  润新知