两种分布式锁实现方案(一)

一。为何使用分布式锁?
当应用服务器数量超过1台,对相同数据的访问可能造成访问冲突(特别是写冲突)。单纯使用关系数据库比如MYSQL的应用可以借助于事务来实现锁,也可以使用版本号等实现乐观锁,最大的缺陷就是可用性降低(性能差)。对于GLEASY这种满足大规模并发访问请求的应用来说,使用数据库事务来实现数据库就有些捉襟见肘了。另外对于一些不依赖数据库的应用,比如分布式文件系统,为了保证同一文件在大量读写操作情况下的正确性,必须引入分布式锁来约束对同一文件的并发操作。

二。对分布式锁的要求
1.高性能(分布式锁不能成为系统的性能瓶颈)
2.避免死锁(拿到锁的结点挂掉不会导致其它结点永远无法继续)
3.支持锁重入

三。方案1,基于zookeeper的分布式锁

[java] view plain copy
 
    1. /** 
    2.  * DistributedLockUtil.java 
    3.  * 分布式锁工厂类,所有分布式请求都由该工厂类负责 
    4.  */  
    5. public class DistributedLockUtil {  
    6.     private static Object schemeLock = new Object();  
    7.     private static Object mutexLock = new Object();  
    8.     private static Map<String, Object> mutexLockMap = new ConcurrentHashMap();  
    9.     private String schema;  
    10.     private Map<String, DistributedReentrantLock> cache = new ConcurrentHashMap<String, DistributedReentrantLock>();  
    11.   
    12.     private static Map<String, DistributedLockUtil> instances = new ConcurrentHashMap();  
    13.   
    14.     public static DistributedLockUtil getInstance(String schema) {  
    15.         DistributedLockUtil u = instances.get(schema);  
    16.         if (u == null) {  
    17.             synchronized (schemeLock) {  
    18.                 u = instances.get(schema);  
    19.                 if (u == null) {  
    20.                     u = new DistributedLockUtil(schema);  
    21.                     instances.put(schema, u);  
    22.                 }  
    23.             }  
    24.         }  
    25.         return u;  
    26.     }  
    27.   
    28.     private DistributedLockUtil(String schema) {  
    29.         this.schema = schema;  
    30.     }  
    31.   
    32.     private Object getMutex(String key) {  
    33.         Object mx = mutexLockMap.get(key);  
    34.         if (mx == null) {  
    35.             synchronized (mutexLock) {  
    36.                 mx = mutexLockMap.get(key);  
    37.                 if (mx == null) {  
    38.                     mx = new Object();  
    39.                     mutexLockMap.put(key, mx);  
    40.                 }  
    41.             }  
    42.         }  
    43.         return mx;  
    44.     }  
    45.   
    46.     private DistributedReentrantLock getLock(String key) {  
    47.         DistributedReentrantLock lock = cache.get(key);  
    48.         if (lock == null) {  
    49.             synchronized (getMutex(key)) {  
    50.                 lock = cache.get(key);  
    51.                 if (lock == null) {  
    52.                     lock = new DistributedReentrantLock(key, schema);  
    53.                     cache.put(key, lock);  
    54.                 }  
    55.             }  
    56.         }  
    57.         return lock;  
    58.     }  
    59.   
    60.     public void reset() {  
    61.         for (String s : cache.keySet()) {  
    62.             getLock(s).unlock();  
    63.         }  
    64.     }  
    65.   
    66.     /** 
    67.      * 尝试加锁 
    68.      * 如果当前线程已经拥有该锁的话,直接返回false,表示不用再次加锁,此时不应该再调用unlock进行解锁 
    69.      * 
    70.      * @param key 
    71.      * @return 
    72.      * @throws InterruptedException 
    73.      * @throws KeeperException 
    74.      */  
    75.     public LockStat lock(String key) throws InterruptedException, KeeperException {  
    76.         if (getLock(key).isOwner()) {  
    77.             return LockStat.NONEED;  
    78.         }  
    79.         getLock(key).lock();  
    80.         return LockStat.SUCCESS;  
    81.     }  
    82.   
    83.     public void clearLock(String key) throws InterruptedException, KeeperException {  
    84.         synchronized (getMutex(key)) {  
    85.             DistributedReentrantLock l = cache.get(key);  
    86.             l.clear();  
    87.             cache.remove(key);  
    88.         }  
    89.     }  
    90.   
    91.     public void unlock(String key, LockStat stat) throws InterruptedException, KeeperException {  
    92.         unlock(key, stat, false);  
    93.     }  
    94.   
    95.     public void unlock(String key, LockStat stat, boolean keepalive) throws InterruptedException, KeeperException {  
    96.         if (stat == null) return;  
    97.         if (LockStat.SUCCESS.equals(stat)) {  
    98.             DistributedReentrantLock lock = getLock(key);  
    99.             boolean hasWaiter = lock.unlock();  
    100.             if (!hasWaiter && !keepalive) {  
    101.                 synchronized (getMutex(key)) {  
    102.                     lock.clear();  
    103.                     cache.remove(key);  
    104.                 }  
    105.             }  
    106.         }  
    107.     }  
    108.   
    109.     public static enum LockStat {  
    110.         NONEED,  
    111.         SUCCESS  
    112.     }  
    113. }  
原文地址:https://www.cnblogs.com/panxuejun/p/8360537.html