我是使用 Hazelcast 的新手。我在我的 Web 应用程序中使用 Hazelcast 3.6-EA 作为数据存储。该应用程序将在多个实例上运行,因此当多个线程尝试使用同一个 Map 时,我需要实现锁定机制以避免竞争条件。
期望的行为如下:开始使用 Map 的第一个实例应该锁定它并执行所需的更新。另一个实例应该看到 Map 已锁定并跳过执行任何更新。
因此,这种锁定的主要好处应该是避免两次执行相同的代码。
public void consumePerformances(Date date) {
Collection<Integer> performancesId = timeformPerformanceService.getPerformancesIds();
timeFormService.getPerformancesByMeetingDate(date, new DataCallback<List<Performance>>() {
@Override
public void onResponse(List<Performance> performances) {
Map<Integer, Performance> newPerformancesMap =
performances.stream().collect(Collectors.toMap(Performance::getPerformanceId, Function.identity()));
newPerformancesMap.entrySet().stream().filter(element -> performancesId.contains(element.getKey()))
.forEach(element -> element.getValue().setUpdateDate(date));
timeformPerformanceService.save(newPerformancesMap.values());
}
@Override
public void onError(Throwable throwable) {
}
});
}
public void save(Collection<Performance> performances) {
LOGGER.info("Save performances to the hazelcast");
IMap<Integer, Performance> map = hazelcastInstance.getMap(PERFORMANCE_CACHE_NAME);
performances.forEach(item -> {
try {
if (map.tryLock(item.getPerformanceId(), 1, TimeUnit.SECONDS, 300, TimeUnit.SECONDS)) {
try {
map.put(item.getPerformanceId(), item);
} finally {
try {
map.unlock(item.getPerformanceId());
} catch (IllegalMonitorStateException e) {
LOGGER.error("Lock was released, due to lease time was expired");
}
}
} else {
LOGGER.info("Lock on key: {} is not released yet", map.get(item.getPerformanceId()));
}
} catch (InterruptedException e) {
LOGGER.error("Lock error. Key could not be equal to null");
}
}
);
}
我怀疑我是否正确理解了锁定机制,以及上面实施的行为是否给了我想要的结果。
我会很感激任何详细的解释。
另外,告诉我,如果线程锁定地图,而另一个只是执行get(key)
操作,会有什么行为?