lx-dong
lx-dong
我们的解决方式是对 CacheResult#waitForResult 方法加synchronized.. public void waitForResult(Duration timeout) { synchronized (this) { if (resultCode != null) { return; } try { ResultData resultData = future.toCompletableFuture().get( timeout.toMillis(), TimeUnit.MILLISECONDS); fetchResultSuccess(resultData); } catch (TimeoutException...
感觉最好的解决方式应该是 CacheEvent 这个事件中传递的是一个final的只读结果,而不是一个有可能为中间态且与主线程共享的对象
> 具体错误是什么?可能是有的地方没有加volatile 1. 第一个报错的空指针在 MultiLevelCache#do_GET -> #unwrapHolder -> Objects.requireNonNull(h); 2. 另外一个是缓存返回null(期望值肯定是非空) 具体原因就是CacheMonitor 消费event的时间比主线程早,导致isSuccess() == true,但是value还没set完成。 根本原因是 CacheGetResult 的 resultCode, value, holder 属性读写不是原子的,并发就有问题,类似读写锁解决的问题场景。除了synchronized,我也对这几个参数加了volatile。
另外 CacheResult#isSuccess,#getResultCode 等方法不仅仅是一个get方法,里面有#waitForResult这种写操作,这就比较坑了,实现CacheMonitor时一旦调用了这些方法又不知道内部实现的话肯定踩坑。