1. private final static int INIT_VERSION = 2;
    2. /**
    3. * 单位为毫秒; 获取的锁的自动释放时间是100ms.
    4. */
    5. private final static int DEFAULT_EXPIRE_TIME = 100;
    6. /**
    7. * 单位为毫秒; 获取锁时, 默认的等待时间. 重试次数计算: DEFAULT_TIMEOUT/DEFAULT_LOCK_RETRY_INTERVAL
    8. */
    9. private final static int DEFAULT_TIMEOUT = 200;
    10. /**
    11. * 单位为毫秒; 获取锁时, 默认重试的时间间隔是50ms.
    12. */
    13. private final static int DEFAULT_LOCK_RETRY_INTERVAL = 50;
    14. /**
    15. * 释放锁时, 默认进行五次重试.
    16. */
    17. private final static int DEFAULT_UNLOCK_RETRY_COUNT = 5;
    18. private ThreadLocal<String> threadValue = new ThreadLocal<String>();
    19. @Override
    20. public boolean lock(String key) {
    21. return lock(key, DEFAULT_EXPIRE_TIME, DEFAULT_TIMEOUT);
    22. }
    23. @Override
    24. public boolean lock(String key, int expireTime, long timeout) {
    25. long start = System.currentTimeMillis();
    26. for (; ; ) {
    27. boolean rs = tryLock(key, expireTime);
    28. if (rs) {
    29. return true;
    30. }
    31. long current = System.currentTimeMillis();
    32. if ((current - start + DEFAULT_LOCK_RETRY_INTERVAL) > timeout) {
    33. LOG.error("lock timeout. key:{}", key);
    34. return false;
    35. }
    36. waitToRetry();
    37. }
    38. }
    39. @Override
    40. public boolean tryLock(String key, int expireTime) {
    41. try {
    42. DataEntry<String> dataEntry = super.get(key);
    43. // 如果已经有值, 则判断是否是重入场景
    44. if (dataEntry != null && !StringUtils.isBlank(dataEntry.getValue())) {
    45. String value = dataEntry.getValue();
    46. return threadValue.get() != null && threadValue.get().equals(value);
    47. }
    48. // 如果没有值, 则设置值, 获取锁
    49. String value = threadValue.get();
    50. if (value == null) {
    51. value = generateValue();
    52. threadValue.set(value);
    53. }
    54. super.setWithVersion(key, value, INIT_VERSION, expireTime);
    55. return true;
    56. } catch (Exception e) {
    57. LOG.error("tryLock error. key:{}", key, e);
    58. return false;
    59. }
    60. }
    61. @Override
    62. public boolean unlock(String key) {
    63. String value = threadValue.get();
    64. for (int i = 0; i < DEFAULT_UNLOCK_RETRY_COUNT; i++) {
    65. try {
    66. DataEntry<String> stringDataEntry = super.get(key);
    67. if (null != stringDataEntry && StringUtils.isNotBlank(
    68. stringDataEntry.getValue()) && StringUtils.isNotBlank(value) && StringUtils.equals(
    69. stringDataEntry.getValue(), value)) {
    70. super.remove(key);
    71. threadValue.remove();
    72. return true;
    73. } else {
    74. LOG.error("unlock error. key:{}", key);
    75. return false;
    76. }
    77. } catch (Exception e) {
    78. LOG.error("unlock error. key:{}", key, e);
    79. }
    80. }
    81. LOG.error("unlock fail after retry ${} times, tair service may be unavailable now", DEFAULT_UNLOCK_RETRY_COUNT);
    82. return false;
    83. }
    84. private void waitToRetry() {
    85. try {
    86. Thread.sleep(DEFAULT_LOCK_RETRY_INTERVAL);
    87. } catch (Exception e) {
    88. LOG.warn("waitToRetry error", e);
    89. }
    90. }
    91. private String generateValue() {
    92. return Thread.currentThread().getName() + "_" + UUID.randomUUID().toString();
    93. }