synchronized
关键字和各类 Lock
锁,可是这种方式加的锁只能保证在单项目或者说同一个jvm中起做用.可是在如今的分布式环境下就不能很好的应对分布式环境的加锁需求,因此有了分布式锁通常过程分为:加锁,解锁java
SET key value NX PX 2000
<dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.9.0</version> </dependency>
说明:通常设置分布式锁的时候,好比:金额操做会在多个地方,使用同一个key好比用户帐号,这个时候若是没获取到锁,确定不如直接返回报错或异常或者直接结束,应该有个重试竞争机制redis
/** * @param jedis jedis 链接 * @param lockKey 传入的锁标识 * @param tryTimeoutMs 尝试获取锁的时间 * @param lockTimeoutMS 锁的超时时间 * @return 返回设置key对应的value值 */ public static String lock(Jedis jedis,String lockKey, long tryTimeoutMs, int lockTimeoutMS) { String retTip = null; String identifier = UUID.randomUUID().toString(); try { long end = System.currentTimeMillis() + tryTimeoutMs; while (System.currentTimeMillis() < end) { String result = jedis.set(lockKey, identifier, "NX", "PX", lockTimeoutMS); if ("OK".equals(result)) { retTip = identifier; break; } try { Thread.sleep(10); } catch (InterruptedException ie) { Thread.currentThread().interrupt(); } } } catch (Exception e) { return "err"; } finally { // 异常释放链接 if (jedis != null) { jedis.close(); } } return retTip; }
// 调用,循环屡次尝试获取锁 public static void test(String[] args) { String key = "xxx";// key 标识 try { // 进行对应的操做 int cnt=0; while(true) { cnt++; if (cnt > 5) { throw new RuntimeException(); } String resTip = lock(jedisPool.getResource(),key, 6000, 5000); if (!org.springframework.util.StringUtils.isEmpty(resTip)) { if ("err".equals(resTip)) {//redis 出错 throw new RuntimeException();// 异常退出 } // 获取锁以后的操做 releaseLock(key, resTip); break; } } }catch (Exception e) { e.printStackTrace(); } } private static final Long RELEASE_SUCCESS = 1L; /** * 释放分布式锁 * @param jedis Redis客户端 * @param lockKey 锁 key * @param requestId 请求标识 value * @return 是否释放成功 */ public static boolean releaseLock(Jedis jedis, String lockKey, String requestId) { String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end"; Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId)); if (RELEASE_SUCCESS.equals(result)) { return true; } return false; }