美文网首页
caffeine源码分析——如何做到原子性的

caffeine源码分析——如何做到原子性的

作者: 黄云斌huangyunbin | 来源:发表于2018-09-18 17:38 被阅读0次
    caffeine的load put 和invalidate操作都是原子的,这个意思是这3个操作是互斥的,load和put是不能同时执行的,load和invalidate也是不能同时执行的。

    先load再invalidate,invalidate操作是要等load操作执行完的。如果load操作执行比较慢,那invalidate操作就要等很久了。

    这样做有什么好处呢,可以保证结果完全符合预期。

    这种方式和guava是不同的,guava是不阻塞的。
    先load再invalidate,invalidate操作是马上执行完的,不需要等待load这种耗时操作执行完。这个其实不合预期的,根本达不到invalidate的效果了。
    先load再invalidate,本意是要让当前的load操作失效,但是load操作时间比较长,load操作结束是在invalidate之后了,失效不了这吃load操作。

    说概念可能比较抽象,我们来举个例子:
    public static void main(String[] args) throws Exception {
    
            final AtomicInteger atomicInteger = new AtomicInteger();
            final LoadingCache<String, String> cache = CacheBuilder.newBuilder().maximumSize(500)
                    .build(new CacheLoader<String, String>() {
                        @Override
                        public String load(String s) throws Exception {
                            Thread.sleep(1000);
                            return atomicInteger.incrementAndGet() + "";
                        }
                    });
    
            cache.get("test");
            cache.invalidate("test");
    
            new Thread() {
                @Override
                public void run() {
                    try {
                        String value = cache.get("test");
                    } catch (ExecutionException e) {
                        e.printStackTrace();
                    }
                }
            }.start();
    
            new Thread() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    long start = System.currentTimeMillis();
                    cache.invalidate("test");
                    System.out.println("use ms:" + (System.currentTimeMillis() - start));
                }
            }.start();
    
    
            Thread.sleep(1200);
            System.out.println("========" + cache.asMap());
            System.out.println("========" + cache.get("test"));
    
        }
    

    结果是:
    use ms:0
    ========{test=2}
    ========2

    其实我们期望的结果是3的,不能满足我们的期望。

    再看看caffeine,这个时候原子性就的好处就得到体现了。
    public static void main(String[] args) throws Exception {
            AtomicInteger atomicInteger=new AtomicInteger();
            LoadingCache<String, String> cache = Caffeine.newBuilder().maximumSize(3).build(key -> {
                Thread.sleep(1000);
                return atomicInteger.incrementAndGet()+"";
            });
    
            cache.get("test");
            cache.invalidate("test");
    
            new Thread() {
                @Override
                public void run() {
                    cache.get("test");
    
                }
            }.start();
    
            new Thread() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    long start = System.currentTimeMillis();
                    cache.invalidate("test");
                    System.out.println("use ms:"+(System.currentTimeMillis() - start));
                }
            }.start();
    
    
            Thread.sleep(1200);
            System.out.println("========" + cache.asMap());
            System.out.println("========" + cache.get("test"));
    
        }
    
    结果是:

    use ms:802
    ========{}
    ========3
    这个就是我们想要的结果了,虽然invalidate阻塞了一段时间。

    caffeine实现原理

    其实原理很简单,caffeine的存储就是ConcurrentHashMap,利用了ConcurrentHashMap自己的node节点锁。
    invalidate操作对应的就是remove方法
    image.png

    可以看到remove是加锁的

    而load方法对应的是compute方法
    image.png

    remappingFunction.apply 这里对应的就是我们具体的load的方法内容

    compute方法也是加锁的,key相同的情况下,compute是和remove加的相同的锁的。

    相关文章

      网友评论

          本文标题:caffeine源码分析——如何做到原子性的

          本文链接:https://www.haomeiwen.com/subject/nuspnftx.html