zookeeper分布式锁(curator)
maven配置文件:
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>2.3.0</version>
</dependency>
代码示例:
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
CuratorFramework client = CuratorFrameworkFactory.newClient(
"192.168.31.184:2181,192.168.31.207:2181,192.168.31.192:2181",
retryPolicy);
client.start();
InterProcessMutex lock = new InterProcessMutex(client, "/locks/lock_01");
lock.acquire();
核心源码:
创建一个临时有序节点,然后获取到自己在节点中的位置,如果是在第0位,则获取锁成功,把节点信息放入ConcurrentMap<Thread, LockData> threadData这个map中。如果不是第0位,则wait等待,并注册一个watch,对它上一个节点进行监控(监控上一个节点是否存在)。
private boolean internalLock(long time, TimeUnit unit) throws Exception
{
Thread currentThread = Thread.currentThread();
LockData lockData = threadData.get(currentThread);
if ( lockData != null )
{
// re-entering
lockData.lockCount.incrementAndGet();
return true;
}
String lockPath = internals.attemptLock(time, unit, getLockNodeBytes());
if ( lockPath != null )
{
LockData newLockData = new LockData(currentThread, lockPath);
threadData.put(currentThread, newLockData);
return true;
}
return false;
}
String attemptLock(long time, TimeUnit unit, byte[] lockNodeBytes) {
ourPath =client.create().creatingParentsIfNeeded().withProtection()
.withMode(CreateMode.EPHEMERAL_SEQUENTIAL).forPath(path, localLockNodeBytes);
asTheLock = internalLockLoop(startMillis, millisToWait, ourPath);
}
释放锁主要逻辑:删除当前持有锁的临时节点,并移除当前线程的LockData。
public void release() throws Exception
{
Thread currentThread = Thread.currentThread();
LockData lockData = threadData.get(currentThread);
int newLockCount = lockData.lockCount.decrementAndGet();
if ( newLockCount > 0 )
{
return;
}
try
{internals.releaseLock(lockData.lockPath);}
finally
{threadData.remove(currentThread);}
}