如何在没有竞争条件的情况下将 ByteBuf 存储在 Caffeine LoadingCache 中?

问题描述 投票:0回答:1

我有一个

LoadingCache
,可以从一些数据加载 Netty
ByteBuf
。一旦条目被逐出,我需要能够使用
release()
释放此数据,但是存在一种竞争条件,即在我能够
retain()
之前条目已被逐出,并且返回的
ByteBuf
无效。

这是我正在尝试做的一个示例 - 当在 get 和保留之间调用删除侦听器时,会发生竞争。

LoadingCache<String, ByteBuf> cache = Caffeine.newBuilder()
    .maximumSize(128)
    .evictionListener(
        (RemovalListener<String, ByteBuf>) (string, buf, removalCause) -> {
            buf.release();
        }
    )
    .build(
        key -> {
            ByteBuf byteBuf = null;
            // TODO: Create the ByteBuf from a pool
            return byteBuf;
        }
    );

ByteBuf buffer = cache.get("hello").retain();

// If the entry is evicted between call to get and the retain then a race condition occurs
// That means the reference count drops to 0 before the retain is invoked

有没有办法让 Caffeine 在从 get 返回之前安全地、原子地调用保留?

java netty caffeine-cache netty4
1个回答
0
投票

您可以使用

asMap().compute
对条目执行读/写操作。

Cache<String, ByteBuf> cache = Caffeine.newBuilder()
    .evictionListener((String string, ByteBuf buf, RemovalCause cause) -> buf.release())
    .maximumSize(128)
    .build();

ByteBuf buffer = cache.asMap().compute(key, (k, buf) -> {
  if (buf == null) {
    buf = // TODO: Create the ByteBuf from a pool
  }
  buf.retain();
  return buf;
});

您可能还对 固定 感兴趣,您可以通过指定该条目消耗零容量来将其标记为不可逐出,因此它将被大小逐出跳过。

Cache<String, ByteBuf> cache = Caffeine.newBuilder()
    .weigher((String string, ByteBuf buf) -> (buf.refCnt() == 0) ? 1 : 0)
    .maximumWeight(128)
    .build();

public ByteBuf acquire(String key) {
  // above
}
public void release(String key) {
  cache.asMap().compute(key, (k, buf) -> {
    buf.release();
    return buf;
  });
}
© www.soinside.com 2019 - 2024. All rights reserved.