java 怎么实现分布式锁,给个示例方法吧
时间: 2024-05-14 16:14:49 浏览: 75
实现分布式锁可以使用以下方法:
1. 使用Redis实现分布式锁
Redis是一个高性能的内存数据库,可以使用Redis的SETNX命令来实现分布式锁。SETNX命令可以将一个key设置为一个value,但是只有在该key不存在的情况下才会设置成功。我们可以将锁的名字作为key,将锁的持有者作为value,如果SETNX命令返回1,表示获取锁成功。
示例代码:
```java
import redis.clients.jedis.Jedis;
public class RedisLock {
private Jedis jedis;
public RedisLock(Jedis jedis) {
this.jedis = jedis;
}
public boolean lock(String key, String value, int expireTime) {
Long result = jedis.setnx(key, value);
if (result == 1) {
jedis.expire(key, expireTime);
return true;
} else {
return false;
}
}
public boolean unlock(String key, String value) {
String lockValue = jedis.get(key);
if (lockValue != null && lockValue.equals(value)) {
jedis.del(key);
return true;
} else {
return false;
}
}
}
```
2. 使用Zookeeper实现分布式锁
Zookeeper是一个分布式协调服务,可以使用Zookeeper的临时节点来实现分布式锁。我们创建一个临时节点来表示锁,如果创建成功,表示获取锁成功。当锁的持有者释放锁时,该节点会被自动删除。
示例代码:
```java
import java.util.List;
import java.util.SortedSet;
import java.util.TreeSet;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;
public class ZookeeperLock {
private ZooKeeper zk;
private String lockName;
private String lockPath;
private String nodeName;
public ZookeeperLock(ZooKeeper zk, String lockName) {
this.zk = zk;
this.lockName = lockName;
this.lockPath = "/locks/" + lockName;
}
public boolean lock() throws KeeperException, InterruptedException {
// 创建锁的根节点
Stat stat = zk.exists(lockPath, false);
if (stat == null) {
zk.create(lockPath, new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
}
// 创建临时顺序节点
nodeName = zk.create(lockPath + "/lock_", new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
// 获取所有子节点
List<String> children = zk.getChildren(lockPath, false);
// 获取所有比自己小的节点
SortedSet<String> smallerNodes = new TreeSet<String>();
for (String child : children) {
if (nodeName.endsWith(child)) {
break;
}
smallerNodes.add(child);
}
// 如果自己是最小的节点,表示获取锁成功
if (smallerNodes.isEmpty()) {
return true;
}
// 监听比自己小的最后一个节点的删除事件
String lastSmallerNode = smallerNodes.last();
Stat lastSmallerNodeStat = zk.exists(lockPath + "/" + lastSmallerNode, new Watcher() {
public void process(WatchedEvent event) {
synchronized (ZookeeperLock.this) {
ZookeeperLock.this.notifyAll();
}
}
});
// 等待锁的释放
if (lastSmallerNodeStat != null) {
synchronized (this) {
wait();
}
}
return true;
}
public boolean unlock() throws KeeperException, InterruptedException {
zk.delete(nodeName, -1);
return true;
}
}
```
阅读全文