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

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加的相同的锁的。
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 简介 ConcurrentHashMap 是 Java concurrent 包的重要成员。本文将结合 Java ...
    翼徳阅读 1,741评论 3 32
  • 本文是我自己在秋招复习时的读书笔记,整理的知识点,也是为了防止忘记,尊重劳动成果,转载注明出处哦!如果你也喜欢,那...
    波波波先森阅读 11,638评论 4 56
  • 持续行动会给你积累好多力量,本来你觉得很难做到的事情,在每天的持续行动之中,不知不觉积累了向上的力量。比如,我原本...
    Elaine匹阅读 171评论 0 0
  • 每一天的反反复复找工作,从这里去那里,从今天到明天,一天天的时间都浪费掉了,老是想着依赖别人,自己没勇气跨出那一步...
    眷芳阅读 220评论 0 0
  • 是不是有许多人都在抱怨现在的生活,觉得好累,会有好多更好种可能,或许会开一家令自己舒服的小店,享受着生活。 现在我...
    我家门前的柿树阅读 356评论 0 1

友情链接更多精彩内容