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

caffeine的load put 和invalidate操作都是原子的,這個意思是這3個操作是互斥的巡通,load和put是不能同時執(zhí)行的赊舶,load和invalidate也是不能同時執(zhí)行的。

先load再invalidate摆出,invalidate操作是要等load操作執(zhí)行完的掖举。如果load操作執(zhí)行比較慢快骗,那invalidate操作就要等很久了娜庇。

這樣做有什么好處呢塔次,可以保證結(jié)果完全符合預期。

這種方式和guava是不同的名秀,guava是不阻塞的励负。
先load再invalidate,invalidate操作是馬上執(zhí)行完的匕得,不需要等待load這種耗時操作執(zhí)行完继榆。這個其實不合預期的巾表,根本達不到invalidate的效果了。
先load再invalidate略吨,本意是要讓當前的load操作失效集币,但是load操作時間比較長,load操作結(jié)束是在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"));

    }

結(jié)果是:
use ms:0
========{test=2}
========2

其實我們期望的結(jié)果是3的秽之,不能滿足我們的期望当娱。

再看看caffeine,這個時候原子性就的好處就得到體現(xiàn)了考榨。
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"));

    }
結(jié)果是:

use ms:802
========{}
========3
這個就是我們想要的結(jié)果了跨细,雖然invalidate阻塞了一段時間。

caffeine實現(xiàn)原理

其實原理很簡單河质,caffeine的存儲就是ConcurrentHashMap冀惭,利用了ConcurrentHashMap自己的node節(jié)點鎖。
invalidate操作對應的就是remove方法
image.png

可以看到remove是加鎖的

而load方法對應的是compute方法
image.png

remappingFunction.apply 這里對應的就是我們具體的load的方法內(nèi)容

compute方法也是加鎖的掀鹅,key相同的情況下云头,compute是和remove加的相同的鎖的。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末淫半,一起剝皮案震驚了整個濱河市溃槐,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌科吭,老刑警劉巖昏滴,帶你破解...
    沈念sama閱讀 218,284評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異对人,居然都是意外死亡谣殊,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評論 3 395
  • 文/潘曉璐 我一進店門牺弄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來姻几,“玉大人,你說我怎么就攤上這事势告∩甙疲” “怎么了?”我有些...
    開封第一講書人閱讀 164,614評論 0 354
  • 文/不壞的土叔 我叫張陵咱台,是天一觀的道長络拌。 經(jīng)常有香客問我,道長回溺,這世上最難降的妖魔是什么春贸? 我笑而不...
    開封第一講書人閱讀 58,671評論 1 293
  • 正文 為了忘掉前任混萝,我火速辦了婚禮,結(jié)果婚禮上萍恕,老公的妹妹穿的比我還像新娘逸嘀。我一直安慰自己,他們只是感情好允粤,可當我...
    茶點故事閱讀 67,699評論 6 392
  • 文/花漫 我一把揭開白布厘熟。 她就那樣靜靜地躺著,像睡著了一般维哈。 火紅的嫁衣襯著肌膚如雪绳姨。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,562評論 1 305
  • 那天阔挠,我揣著相機與錄音飘庄,去河邊找鬼。 笑死购撼,一個胖子當著我的面吹牛跪削,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播迂求,決...
    沈念sama閱讀 40,309評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼碾盐,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了揩局?” 一聲冷哼從身側(cè)響起毫玖,我...
    開封第一講書人閱讀 39,223評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎凌盯,沒想到半個月后付枫,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,668評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡驰怎,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,859評論 3 336
  • 正文 我和宋清朗相戀三年阐滩,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片县忌。...
    茶點故事閱讀 39,981評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡掂榔,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出症杏,到底是詐尸還是另有隱情装获,我是刑警寧澤,帶...
    沈念sama閱讀 35,705評論 5 347
  • 正文 年R本政府宣布鸳慈,位于F島的核電站饱溢,受9級特大地震影響喧伞,放射性物質(zhì)發(fā)生泄漏走芋。R本人自食惡果不足惜绩郎,卻給世界環(huán)境...
    茶點故事閱讀 41,310評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望翁逞。 院中可真熱鬧肋杖,春花似錦、人聲如沸挖函。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽怨喘。三九已至津畸,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間必怜,已是汗流浹背肉拓。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留梳庆,地道東北人暖途。 一個月前我還...
    沈念sama閱讀 48,146評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像膏执,于是被迫代替她去往敵國和親驻售。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,933評論 2 355

推薦閱讀更多精彩內(nèi)容