精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

Java volatile 關(guān)鍵字到底是什么

開發(fā) 前端
由于 C2 編譯器的激進(jìn)優(yōu)化,編譯后的機(jī)器碼不再判斷 running 變量,從而產(chǎn)生了內(nèi)存可見性問題。而即使 C2 編譯后的機(jī)器指令依然會執(zhí)行安全點(diǎn)檢查。想想是不是可以利用安全點(diǎn)檢查機(jī)制,用一些操作來讓進(jìn)程停止?比如提交執(zhí)行一次 GC、打個(gè)斷點(diǎn)之類的。

一、前言

volatile 作為 Java 的基礎(chǔ)關(guān)鍵字,一直是個(gè)熟悉又神秘的存在。我們在日常做并發(fā)編程的過程中經(jīng)常用到,我們知道在什么場景下需要用到,但卻始終不清楚底層究竟做了什么。互聯(lián)網(wǎng)上搜出來的大多數(shù)博客都在解釋 volatile 關(guān)鍵字是為了解決指令重排序、內(nèi)存可見性問題,或是什么內(nèi)存屏障、緩存一致性協(xié)議一類“形而上的詞匯”。而究竟什么是指令重排序,為什么要重新排序,什么是可見性問題,底層原理是什么,volatile 又是如何解決的卻鮮有提及。引得 Java 開發(fā)者們?nèi)珈F里看花,線上線下充滿了疑惑的空氣。

本文將淺淺探究一下這一切的底層原理,一起來學(xué)習(xí)“沒有用”的知識,各位看官看懂了可以出去和面試官對線。

二、指令重排序

在了解指令重排序問題之前,我們先來看一個(gè)由指令重排序造成并發(fā)問題的例子:

static int x = 0, y = 0;
static int a = 0, b = 0;


public static void main(String[] args) throws InterruptedException {
    for (int i = 0; true; i++) {
        x = 0; y = 0; a = 0; b = 0;
        Thread one = new Thread(new Runnable() {
            public void run() {
                a = 1;
                x = b;
            }
        });
        Thread other = new Thread(new Runnable() {
            public void run() {
                b = 1;
                y = a;
            }
        });
        one.start();other.start();
        one.join();other.join();
        if (x == 0 && y == 0) {
            System.err.println("bingo!i: " + i);
            break;
        }
    }
}

happens-before 八條原則

  • 程序次序規(guī)則:在一個(gè)線程內(nèi),按照控制流順序,書寫在前面的操作先行發(fā)生于書寫在后面的操作。
  • 管程鎖定規(guī)則:一個(gè) unlock 操作先行發(fā)生于后面對同一個(gè)鎖的 lock 操作。
  • volatile 變量規(guī)則:對一個(gè) volatile 變量的寫操作先行發(fā)生于后面對這個(gè)變量的讀操作。
  • 線程啟動規(guī)則:Thread 對象 start()方法先行發(fā)生于此線程的每一個(gè)動作。
  • 線程終止規(guī)則:線程A等待線程B完成,在線程A中調(diào)用線程B的join()方法實(shí)現(xiàn)),當(dāng)線程B完成后(線程A調(diào)用線程B的join()方法返回),則線程A能夠訪問到線程B對共享變量的操作。
  • 線程中斷規(guī)則:對線程 interrupt() 方法的調(diào)用先行,發(fā)生于被中斷線程的代碼,檢測到中斷事件的發(fā)生,可以通過 Thread.interrupted()方法檢測到是否有中斷發(fā)生。
  • 對象終結(jié)規(guī)則:一個(gè)對象的初始化完成(構(gòu)造函數(shù)結(jié)束)先行發(fā)生于它的 finalize()方法的開始。
  • 傳遞性:如果操作 A 先行發(fā)生于操作 B,操作 B 先行發(fā)生于操作 C,那就可以得出操作 A 先行發(fā)生于操作 C 的結(jié)論。

hanpens-beofre 是 JVM 對開發(fā)者的保證,即不管 JVM 如何優(yōu)化(JIT 編譯),都會保證上述原則一定成立。而對于開發(fā)者來說,只要了解上述原則,無需硬件交互的復(fù)雜性,也能夠?qū)懗隹深A(yù)測的代碼,從而保證線程安全。

從 hanpens-beofre 中 程序次序規(guī)則 和 線程終止規(guī)則 可得,上述代碼最終運(yùn)行結(jié)果的可能性會有以下幾種:

圖片圖片

可以明顯看出,理論上不會存在 x =0 && y = 0 的運(yùn)行結(jié)果,然而實(shí)際上程序在執(zhí)行了一段時(shí)間后,最終的確產(chǎn)生了 x = 0 && y = 0 的結(jié)果!

圖片圖片

這就引出了 volatile 解決的第一個(gè)問題:避免指令重排序。指令重排序在編譯器和 CPU 層面(亂序執(zhí)行)都會發(fā)生。

CPU 的亂序執(zhí)行

我們知道,CPU 運(yùn)算的本質(zhì)就是不斷獲取下一條指令然后執(zhí)行,編譯器給它什么指令它就執(zhí)行什么,何來的亂序執(zhí)行呢?

這還要從計(jì)算機(jī)的誕生之初講起。

內(nèi)存拖后腿

計(jì)算機(jī)誕生之初,CPU 和內(nèi)存之間的速度差異并不明顯,一切相安無事。隨著科學(xué)的進(jìn)步,CPU 的運(yùn)算速度越來快,根據(jù)摩爾定律計(jì)算,相當(dāng)于 CPU 的性能每年增長 60%,相比之下,內(nèi)存性能的增長卻相對緩慢,每年約為 7%。到今天,CPU 運(yùn)算和內(nèi)存訪問的速度產(chǎn)生了巨大鴻溝,已經(jīng)達(dá)到了 120 倍之多。這時(shí)如果 CPU 還以傳統(tǒng)計(jì)算機(jī)架構(gòu),數(shù)據(jù)從內(nèi)存中讀取的話,將會嚴(yán)重拖慢 CPU 的運(yùn)行速度。

圖片圖片

※ 局部性原理

在程序運(yùn)行過程中,芯片工程師總結(jié)了兩條存在局部性原理:時(shí)間局部性、空間局部性。

  • 時(shí)間局部性:由于在代碼中循環(huán)操作的普遍存在,因此當(dāng)某部分?jǐn)?shù)據(jù)被訪問時(shí),不久后該數(shù)據(jù)很可能會再次被訪問,基于此原理誕生了 CPU 的高速緩存。
  • 空間局部性:由于代碼是順序執(zhí)行的,因此當(dāng)某一份數(shù)據(jù)被訪問時(shí),后續(xù)的數(shù)據(jù)也將很快被訪問,基于此原理誕生了緩存行。
※ CPU 內(nèi)的高速緩存

為了彌補(bǔ) CPU 運(yùn)行速度與內(nèi)存訪問速度之間的巨大差異,提升 CPU 執(zhí)行效率,CPU 在內(nèi)部封裝了高速緩存。

高速緩存是一種靜態(tài)隨機(jī)訪問存儲器(SRAM),相對于使用電容存儲的內(nèi)存(DRAM)來說,速度快得多,訪問速度在納秒級別,終于能勉強(qiáng)不再拖 CPU 后腿了。

圖片圖片

CPU 緩存共分為三級:

  • 按訪問速度從大到小排序?yàn)椋篖1 > L2 > L3
  • 按容量從大到小排序?yàn)椋篖3 > L2 > L1

其中 L3 緩存 CPU 共享,L1、L2 緩存為各 CPU 獨(dú)占。CPU 在訪問內(nèi)存數(shù)據(jù)時(shí),會優(yōu)先從高速緩存中訪問,訪問順序依次為 L1、L2、L3,若高速緩存中都不存在,則再訪問內(nèi)存。

緩存的引入,降低了 CPU 直接訪問內(nèi)存的頻率,大大提升了 CPU 的執(zhí)行效率。

※ 緩存行

根據(jù)空間局部性原理,當(dāng) CPU 訪問了一塊數(shù)據(jù)時(shí),相鄰的數(shù)據(jù)很可能也即將被訪問。那么是否可以通過預(yù)加載相鄰的數(shù)據(jù)到高速緩存中,提升高速緩存的命中率呢?

當(dāng)然可以,我們把預(yù)加載的這部分內(nèi)存數(shù)據(jù)叫做緩存行。

圖片圖片

由圖所示,內(nèi)存被劃分為若干緩存行的塊,緩存行的大小是固定的,通常為 64 字節(jié),高速緩存數(shù)據(jù)塊最小粒度就是緩存行(換句話說,高速緩存內(nèi)的數(shù)據(jù)就是由一個(gè)個(gè)緩存行構(gòu)成的)。當(dāng) CPU 需要訪問位于內(nèi)存的數(shù)據(jù) X 時(shí),會將整個(gè)緩存行同時(shí)加載到高速緩存中,以提升程序后續(xù)執(zhí)行時(shí)的緩存命中率。

CPU 內(nèi)的“分布式”問題

高速緩存是把雙刃劍,在大幅提升 CPU 運(yùn)行效率的同時(shí),也引來了一個(gè) “分布式” 問題。

圖片圖片

記得我們前面說過,CPU 的 L1、L2 緩存是各核心獨(dú)占的,在兩個(gè) CPU 的 L2 緩存同時(shí)加載了同一個(gè)緩存行的情況下,當(dāng) CPU 0 數(shù)據(jù) X 做了寫操作(X = 1),其他 CPU 對這一修改是不可見的,這時(shí) CPU 1 如果依然訪問自己高速緩存中的數(shù)據(jù),勢必會產(chǎn)生數(shù)據(jù)不一致。

為了解決這個(gè)問題,緩存一致性協(xié)議便誕生了。

※  MESI 協(xié)議

緩存一致性協(xié)議有多種,最出名的就是 MESI 協(xié)議。

MESI 是 Modified   Exclusive Shared   Invalid 四個(gè)單詞的縮寫,分別表示緩存行的四種狀態(tài):

  • Modified:表示緩存行中數(shù)據(jù)已經(jīng)被 CPU 修改了。
  • Exclusive:緩存行處于獨(dú)占但尚未修改的狀態(tài),該狀態(tài)表示其他 CPU 不可以預(yù)讀取這個(gè)緩存行到自己的高速緩存中。
  • Shared:表示緩存行數(shù)據(jù)已經(jīng)被多個(gè) CPU 預(yù)加載到緩存中,且各 CPU 均未對該緩存行做修改。
  • Invalid:表示有其他 CPU 修改了該緩存行,緩存行數(shù)據(jù)已經(jīng)失效。

圖片

  • CPU 0 需要修改緩存行中 X 的數(shù)據(jù)時(shí),將當(dāng)前緩存行標(biāo)記為 Modified ,并向總線發(fā)送一條消息,表明緩存行 CPU 0 已經(jīng)修改。
  • CPU 1 接收到該緩存行已失效的消息后,會將本地緩存行標(biāo)記為 Invalid ,并 ACK 給 CPU 0。
  • CPU 0 收到其他 CPU 已經(jīng)將本地緩存行標(biāo)記失效消息后,修改 X 的值。
  • 此時(shí) CPU 0 高速緩存中緩存了 X 的最新值,其他 CPU 如果需要訪問 X ,將會通過總線從CPU 0中獲取。

MESI 協(xié)議非常復(fù)雜,比如各 CPU 之間是如何通信的、多個(gè) CPU 同時(shí)發(fā)送失效事件怎么辦等等。

篇幅所限僅做本文用的著的部分介紹。有興趣了解具體實(shí)現(xiàn)可以點(diǎn)擊 https://www.scss.tcd.ie/Jeremy.Jones/VivioJS/caches/MESI.htm 查看動畫演示。

緩存一致性協(xié)議有效解決了各 CPU 間數(shù)據(jù)一致性問題。那么,代價(jià)是什么呢?

禁止 CPU 摸魚

上圖可以看出 CPU 0 在執(zhí)行修改 X 的值之前,需要與其他 CPU 進(jìn)行通訊,收到其他 CPU 將本地消息修改完成后,才可修改本地緩存行的數(shù)據(jù)。在這期間 CPU 0 一直無事可做。而不管是前面提到過的編譯器指令重排序還是超線程、指令流水線等技術(shù),目的都是在提升 CPU 的運(yùn)行效率,減少 CPU 空跑時(shí)間。如果由于緩存一致性協(xié)議造成 CPU 空閑的話,這對于我們來說顯然是不可接受的!

圖片圖片

為了讓 CPU 滿負(fù)荷運(yùn)轉(zhuǎn),芯片工程師在 CPU 與 L1 緩存之間又加了一層——store buffer。

引入了 store buffer 后,CPU 寫緩存行不再需要等待其他 CPU 回復(fù)消息,而是直接讀寫 store buffer,等到特定時(shí)刻,再將 store buffer 中的數(shù)據(jù) flush 到高速緩存中

圖片圖片

  1. CPU 0 需要修改緩存行中 X 的數(shù)據(jù)時(shí),將當(dāng)前緩存行標(biāo)記為 Modified ,并向總線發(fā)送一條消息。
  2. CPU 0 不再等待 CPU 1 回復(fù),而是直接將修改后的數(shù)據(jù)寫入 store buffer 中。
  3. CPU 0 收到 CPU 1 標(biāo)記緩存已經(jīng)失效的回復(fù)消息后,將 store buffer 中的值 flush 到高速緩存中。

問題會這么完美的解決嗎?

亂序執(zhí)行

現(xiàn)在我們將 store buffer 納入考量,再來回頭看本節(jié)開始的這段代碼:

圖片圖片

最終由于 store buffer 中數(shù)據(jù)的 flush 時(shí)間晚于 CPU 直接寫高速緩存中數(shù)據(jù)的時(shí)間,客觀上產(chǎn)生了 CPU 執(zhí)行的指令順序與實(shí)際代碼中不一致的現(xiàn)象(X = B 早于 A = 1 執(zhí)行,Y = A 早于 B = 1 執(zhí)行),即亂序執(zhí)行。最終得到了(A = 1,B = 1,X = 0,Y = 0)的結(jié)果。

既然發(fā)現(xiàn)了問題,那么要如何解決呢?這就要提到另一項(xiàng)技術(shù):內(nèi)存屏障。

隨著 store buffer 技術(shù)的引入引起的問題還有很多,于是牽扯出一系列其他技術(shù),如 Store Forwarding、Invalidate Queues 等技術(shù)。由于與本文涉及到的內(nèi)容無關(guān),這里就不做贅述了,各位有興趣可以自行了解相關(guān)內(nèi)容。

內(nèi)存屏障

內(nèi)存屏障聽起來比較高大上,實(shí)際總結(jié)起來非常簡單,就一句話:

去告訴 CPU,我在此處定義了一個(gè)內(nèi)存屏障,自這里開始,后續(xù)所有針對高速緩存的寫入,都必須先把 store buffer 中的數(shù)據(jù)全部 flush 回高速緩存中!

圖片圖片

圖片圖片

在 Java 中 volatile 關(guān)鍵字避免 CPU 亂序執(zhí)行的原理其實(shí)就是在訪問 volatile 變量時(shí)添加了內(nèi)存屏障。限制后續(xù)數(shù)據(jù)的寫入操作一定把當(dāng)前 store buffer 中的數(shù)據(jù) flush 到高速緩存中,再通過緩存一致性協(xié)議保證數(shù)據(jù)一致性。

回到本節(jié)一開始的代碼,你一定想到了要如何讓這段程序永遠(yuǎn)執(zhí)行下去的辦法了?

static int x = 0, y = 0;
static volatile int a = 0, b = 0;

沒錯(cuò),我們只需要限制針對數(shù)據(jù) X、Y 的寫操作之前,位于 store buffer 中的數(shù)據(jù) A、B 全部 flush 到高速緩存即可。所以最終的解決方案就是給變量 A、B 添加 volatile 關(guān)鍵字即可!

想想為什么在變量 X、Y 上加 volatile 不可以?說加 4 個(gè) volatile 的那位同學(xué),課后把內(nèi)存屏障這一章節(jié)抄寫 3 遍!

前面說過,指令重排序問題在 CPU 和編譯器層面都存在,CPU 層面說完了,那編譯器層面呢?

編譯器重排序

由于 JIT 編譯后的指令不好扒,我們以 C 語言為例,先來看看下面的 C 語言例子:

int func(int a, int b, int c, int d) {
  return a + b + c + d;
}

如果編譯器不做優(yōu)化,如果完全順從我們代碼語義,以上函數(shù)生成的匯編偽代碼如下:

圖片圖片

圖片圖片

而現(xiàn)代 CPU 會有多個(gè)執(zhí)行單元,例如讀寫單元、運(yùn)算單元,這些執(zhí)行單元之間可以獨(dú)立工作。在執(zhí)行上面的指令時(shí),只能順序執(zhí)行,不能并行執(zhí)行。要想發(fā)揮兩個(gè)執(zhí)行單元的效率,只需調(diào)整一下順序即可:

圖片圖片

圖片圖片

可以看出,雖然指令的數(shù)量一樣,但在對指令做簡單的重新排序后,優(yōu)化一下指令的提交順序,就可以更快的完成任務(wù)。

在 JVM 中,JIT 編譯同樣也會遵循這一原則,在不改變源碼語義的情況下,改變 CPU 指令的執(zhí)行順序,就可以更快的完成運(yùn)算任務(wù),提升執(zhí)行效率。這在單線程情況下運(yùn)行良好,但多線程運(yùn)行時(shí),就可能會存在一些意料之外的問題。

三、可見性問題

再來看另一個(gè)示例:

private static boolean running = true;


public static void main(String[] args) {
    int i = 0;
    Thread thread = new Thread(() -> {
        try {
            Thread.sleep(1000L);
        } catch (InterruptedException e) {
        }
        running = false;
    });
    thread.setDaemon(true);
    thread.start();
    while (running) {
        i++;
    }
    System.err.println(i);
}

上面的程序,并不會按照我們預(yù)期的那樣正常輸出程序結(jié)束后退出,而是會永遠(yuǎn)的執(zhí)行下去(不要嘗試用前文中的 store buffer 來強(qiáng)行解釋這個(gè)問題,store buffer 本質(zhì)上也是個(gè) buffer,在某一時(shí)刻數(shù)據(jù)依然會 flush 到高速緩存中,從而讓其他線程感知到最新的值)。

這就引出 volatile 關(guān)鍵字解決的另一個(gè)問題:內(nèi)存可見性問題。

分層編譯

我們知道,Java 是跨平臺的。一個(gè) Java 源碼文件的執(zhí)行需要兩個(gè)過程:

  1. AOT 編譯:源代碼文件編譯為 class 文件。
  2. JIT 編譯:JVM 加載 class 文件,將 class 文件中字節(jié)碼轉(zhuǎn)換為計(jì)算器可執(zhí)行的機(jī)器指令。

字節(jié)碼的執(zhí)行也有兩種方式:

  1. 解釋執(zhí)行:優(yōu)點(diǎn)是啟動速度快,缺點(diǎn)是需要逐條將字節(jié)碼解釋為機(jī)器指令,開銷大,性能低。
  2. 編譯執(zhí)行(JIT 編譯):優(yōu)點(diǎn)是執(zhí)行效率高,與本地編譯性能基本沒差別,缺點(diǎn)是編譯本身需要消耗 CPU 資源,以及編譯后的指令數(shù)據(jù)需要存儲,需要消耗內(nèi)存空間。

而 JIT 編譯器又分為兩種,Client Compiler、Server Compiler。之所以叫 client,server 是因?yàn)樵谝婚_始設(shè)計(jì)這倆編譯器的時(shí)候,前者是設(shè)計(jì)給客戶端程序用的,就比如像 idea 這種運(yùn)行在個(gè)人電腦上的 Java 程序,不會長時(shí)間使用,反而更注重應(yīng)用的啟動速度以及快速達(dá)到相對較優(yōu)性能。而后者則是設(shè)計(jì)給服務(wù)端程序用的。

HotSpot 虛擬機(jī)帶有一個(gè) Client Compiler —— C1 編譯器。這種編譯器啟動速度快,但是性能相對Server Compiler 來說會差一些。Server Compiler 則更為激進(jìn),優(yōu)化后的性能要比 Client Compiler 高30%以上。HotSpot 虛擬機(jī)則帶有兩個(gè) Server Compiler,默認(rèn)的 C2 以及 Graal。

在 Java 7 之前,需要開發(fā)者根據(jù)服務(wù)的性質(zhì)手動選擇編譯器。自 Java 7 開始,則引入了分層編譯(Tiered Compilation)。

0:由解釋器解釋執(zhí)行

1:C1 NO profiling:執(zhí)行不帶 profiling 的 C1 代碼。

2:C1 LIMITED profiling:執(zhí)行僅帶方法調(diào)用次數(shù)以及循環(huán)回邊執(zhí)行次數(shù) profiling 的 C1 代碼。

3:C1 FULL profiling:執(zhí)行帶所有 profiling 的 C1 代碼。

4:C2:執(zhí)行 C2 代碼。

誰動了我的代碼

運(yùn)行時(shí)編譯有那么多層級,到底是哪層影響了代碼的?

想要探究個(gè)問題很簡單,只需要在JVM啟動參數(shù)里增加 -XX:TieredStopAtLevel=XX 參數(shù)即可。TieredStopAtLevel 是控制 JVM 最大分層編譯級別的參數(shù),當(dāng)我們配置的值 < 4 時(shí),前文的代碼均可以正常終止,那么結(jié)論很明顯了:C2 編譯器全責(zé)!

C2 你在干什么?!

為了探究 C2 編譯對我們代碼做了什么,我們決定使用一款工具:JITWatch。JITWatch 專門用來探究 JIT 編譯后的代碼對應(yīng)匯編指令。

關(guān)于 JITWatch 使用的流程這里就不做贅述了,網(wǎng)上有大量說明。本節(jié)的案例也很好復(fù)現(xiàn),大家可以動手試一試。

我們將前文的源碼文件編譯后,提交以下命令執(zhí)行:

# Ubuntu 22.04 下
java -XX:+UnlockDiagnosticVMOptions -XX:+TraceClassLoading -XX:+LogCompilation -XX:LogFile=~/Desktop/jit.log -XX:+PrintAssembly -XX:+TraceClassLoading Main

接著啟動 JITWatch,加載 jit.log 文件:

圖片圖片

雙擊右側(cè) main 方法,查看 C2 編譯后的結(jié)果:

記得選 OSR(棧上替換) 那個(gè) C2,因?yàn)榇a屬于死循環(huán),代碼塊不會退出,無法完整替換 C2 編譯后的機(jī)器指令,只能通過棧上替換技術(shù)來進(jìn)行。

圖片圖片

綠色框中為我們的核心代碼,我在此處將它放大并增加了注釋,如下:

圖片圖片

什么?無條件跳轉(zhuǎn)?!

可以看出,由于 C2 編譯器的激進(jìn)優(yōu)化,編譯后的機(jī)器碼不再判斷 running 變量,從而產(chǎn)生了內(nèi)存可見性問題。而即使 C2 編譯后的機(jī)器指令依然會執(zhí)行安全點(diǎn)檢查。想想是不是可以利用安全點(diǎn)檢查機(jī)制,用一些操作來讓進(jìn)程停止?比如提交執(zhí)行一次 GC、打個(gè)斷點(diǎn)之類的。

四、總結(jié)

說了那么多,能不能說點(diǎn)有用的?

有的有的,我們在多線程開發(fā)中,只要變量被多個(gè)線程共享,且是可變的,加上 volatile 準(zhǔn)沒錯(cuò):)

責(zé)任編輯:武曉燕 來源: 得物技術(shù)
相關(guān)推薦

2023-10-11 08:29:54

volatileJava原子性

2025-06-13 08:00:00

Java并發(fā)編程volatile

2011-06-14 13:26:27

volatile

2022-06-29 08:05:25

Volatile關(guān)鍵字類型

2019-09-04 14:14:52

Java編程數(shù)據(jù)

2011-06-21 09:50:51

volatile

2009-06-29 18:14:23

Java多線程volatile關(guān)鍵字

2020-09-27 06:53:57

MavenCDNwrapper

2020-10-14 06:22:14

UWB技術(shù)感知

2020-09-22 08:22:28

快充

2010-11-01 01:25:36

Windows NT

2022-08-17 07:53:10

Volatile關(guān)鍵字原子性

2011-04-27 09:30:48

企業(yè)架構(gòu)

2020-07-17 20:15:03

架構(gòu)JMMvolatile

2018-01-19 10:43:06

Java面試官volatile關(guān)鍵字

2021-01-21 21:24:34

DevOps開發(fā)工具

2020-03-05 10:28:19

MySQLMRR磁盤讀

2023-07-12 15:32:49

人工智能AI

2021-07-07 05:07:15

JDKIterator迭代器

2021-02-05 10:03:31

區(qū)塊鏈技術(shù)智能
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

国模私拍一区二区三区| 日韩一区二区三区在线观看| 图片区小说区区亚洲五月| 一本大道伊人av久久综合| 中文字幕乱码亚洲无线精品一区| 日韩精品免费在线视频| 亚洲视频一二三四| 国产精品一区二区日韩| 中文字幕av一区二区三区免费看| 97中文在线观看| 午夜精品一区二| 欧美日韩一卡| 最近2019年好看中文字幕视频| av天堂一区二区| 成人在线观看免费视频| 亚洲成a人在线观看| 亚州欧美一区三区三区在线 | 免费看黄色av| 中文字幕亚洲在线观看| 欧美日本一区二区三区| 激情网站五月天| 污片在线免费观看| 亚洲欧洲美洲综合色网| 欧美日韩国产综合视频在线| 亚洲精品一区二区口爆| 麻豆91在线观看| 国产91|九色| 国产一卡二卡在线播放| 天天做天天爱综合| 一个人看的www久久| 最新在线黄色网址| 北条麻妃一区二区三区在线观看| 欧美日韩国产首页在线观看| 欧在线一二三四区| 超碰在线播放91| 精品176二区| 久久午夜老司机| 国产精品久久久久久久小唯西川 | 91精品蜜臀在线一区尤物| 成人黄色片视频| 888av在线视频| 亚洲影视在线播放| 天堂а√在线中文在线| a视频在线观看| 亚洲丝袜另类动漫二区| 亚洲开发第一视频在线播放| 久久久资源网| 久久久综合视频| 久99久视频| 日韩av视屏| 久久亚区不卡日本| 快播日韩欧美| 欧美成熟毛茸茸| 久久亚洲欧美国产精品乐播| 久久影院理伦片| 亚洲av成人精品毛片| 99精品欧美一区二区三区综合在线| 91福利视频导航| www.成人免费视频| 国产99久久久国产精品免费看 | 日韩美女毛片| 日韩成人久久久| 亚洲国产av一区| 欧美伦理在线视频| 日韩视频免费在线观看| 黄色a级片在线观看| 欧美a级在线| 国内精品久久久久伊人av| 国产精品6666| 久久精品1区| 日韩一区二区三区视频| 欧美性一级生活| 亚洲电影免费| 看黄网站在线| 亚洲在线视频网站| 精品99在线视频| julia一区二区三区中文字幕| 欧美性大战久久久| 亚洲自拍第三页| 国产精品毛片久久久| 日韩av中文字幕在线播放| 91网站免费视频| 99re66热这里只有精品8| 久久av在线播放| 日本在线视频免费| 蜜臀av亚洲一区中文字幕| 91精品啪在线观看麻豆免费| 日韩一区二区三区不卡| 欧美激情综合在线| 国产一级大片免费看| 超碰一区二区| 欧美一区二区三区白人| 亚洲av无码一区二区三区网址| 精品国产一区二区三区小蝌蚪| 久久国产精品电影| 中文字幕免费观看| 国产精品亚洲视频| 日本一区二区三区www| sm国产在线调教视频| 日韩欧美一区二区三区久久| 亚洲日本黄色片| 天海翼精品一区二区三区| 综合国产在线观看| 亚洲免费激情视频| 精品综合久久久久久8888| 国产精品久久久久久久免费大片 | 毛片在线播放视频| 国产资源一区| 日韩激情在线视频| 精品爆乳一区二区三区无码av| 六月天综合网| 成人精品水蜜桃| av网站在线免费播放| 婷婷夜色潮精品综合在线| 日韩在线一区视频| 久久99精品久久久久久园产越南| 久久久久久久999| 在线观看国产精品视频| 91麻豆国产福利在线观看| 乱熟女高潮一区二区在线| 亚洲伊人精品酒店| 一本色道久久88精品综合| 国产精品第9页| 国产精品18久久久久久vr| 天天综合色天天综合色hd| 成人免费网站视频| 亚洲成人av在线播放| 你懂得在线观看| 日本成人在线视频网站| 免费日韩电影在线观看| h片在线观看视频免费免费| 欧美一区二区黄| 女人18毛片毛片毛片毛片区二| 久热国产精品| 欧美一区二区三区成人久久片| 77thz桃花论族在线观看| 欧美丰满少妇xxxxx高潮对白 | 欧美在线观看视频一区| 欧美一级大胆视频| 亚洲欧美色视频| 黄色成人在线播放| 精品熟女一区二区三区| 亚洲午夜黄色| 国产传媒一区| 99热99re6国产在线播放| 欧美成人伊人久久综合网| 91日韩中文字幕| 国产一区日韩二区欧美三区| 一区二区三区视频在线播放| 农村妇女一区二区| 日韩在线视频免费观看高清中文| 国语对白做受69按摩| 国产色综合久久| 一区二区xxx| 欧美hd在线| 亚洲va欧美va在线观看| 91蜜桃在线视频| 日韩一区二区三区免费看| 欧产日产国产v| 成人午夜电影网站| 免费看国产一级片| 亚欧洲精品视频在线观看| 青青a在线精品免费观看| 国产中文字幕在线| 欧美亚洲一区二区在线| 一级片一级片一级片| 国产在线播放一区二区三区| 2022中文字幕| 亚洲性视频大全| 国产精品久久久久av| 日本视频不卡| 精品国一区二区三区| 国偷自拍第113页| 国产午夜精品在线观看| 天堂av手机在线| 亚洲茄子视频| 午夜一区二区三视频在线观看| 91成人福利社区| 高清视频欧美一级| 国产美女视频一区二区三区| 欧美人妖巨大在线| 久久精品国产av一区二区三区| 99精品一区二区三区| 向日葵污视频在线观看| 国产中文一区| 日韩av在线电影观看| 精品麻豆剧传媒av国产九九九| 性色av一区二区三区免费| 高清日韩av电影| 欧美成人欧美edvon| 亚洲欧美精品一区二区三区| 日韩久久一区二区| 91丝袜在线观看| 久久9热精品视频| 一二三四视频社区在线| 国产大片一区| 久久影院理伦片| 欧美国产亚洲精品| 国产成人中文字幕| 新版中文在线官网| 伊人久久精品视频| 日韩在线视频第一页| 欧美日韩不卡一区二区| 欧美特黄aaaaaa| 有码一区二区三区| 极品久久久久久久| 91视频免费播放| 又黄又爽又色的视频| 日韩精品色哟哟| 国产综合中文字幕| 亚洲欧美综合久久久| 欧美日韩在线一二三| 亚洲日本va午夜在线电影| 国产日韩欧美综合| 成人日韩在线| 欧美综合在线第二页| 91福利在线尤物| 欧美成人剧情片在线观看| 国产精品毛片一区二区三区四区| 亚洲成人av片| 亚洲国产日韩在线观看| 欧美日本国产视频| 中文字幕 欧美激情| 狠狠爱在线视频一区| 久草视频免费播放| 日韩毛片视频在线看| 久久亚洲AV无码专区成人国产| 91在线精品秘密一区二区| 亚洲午夜精品在线观看| 精品一区二区免费视频| 欧美一级特黄a| 丝袜美腿一区二区三区| 九色在线视频观看| 亚洲国产二区| 精品少妇在线视频| 伊人蜜桃色噜噜激情综合| 996这里只有精品| 午夜久久久久| 国产一二三四五| 中文字幕人成人乱码| 亚洲天堂第一区| 欧美日本不卡| www.亚洲成人网| 国产精品porn| www.av91| 亚洲经典在线看| 成人免费观看cn| 午夜在线a亚洲v天堂网2018| 播放灌醉水嫩大学生国内精品| 99热免费精品| 欧美女人性生活视频| 另类天堂av| 啊啊啊国产视频| 看电视剧不卡顿的网站| 五月天视频在线观看| 国内精品写真在线观看| 欧洲成人午夜精品无码区久久| 国产精品99久久久久久宅男| 深夜视频在线观看| 波多野洁衣一区| 少妇户外露出[11p]| 国产午夜精品久久久久久免费视 | 黄色av免费在线看| 这里只有精品视频| 免费在线视频欧美| 欧美成人一区在线| 不卡av免费观看| 欧美在线观看网址综合| 韩日一区二区| 亚洲va久久久噜噜噜| 国产乱论精品| 欧美在线一二三区| 中文字幕一区二区精品区| 可以看毛片的网址| 日韩av一区二区三区| 亚洲一级片av| 成人手机在线视频| 国产aⅴ激情无码久久久无码| 欧美国产精品中文字幕| 暗呦丨小u女国产精品| 午夜欧美视频在线观看| 波多野结衣一二区| 欧美一区二区日韩| 日产精品久久久久久久性色| 中文字幕亚洲自拍| 日本伦理一区二区| 国产精品成人免费视频| 欧美成人精品午夜一区二区| 免费观看成人在线| 一区二区三区在线观看免费| 日本福利视频在线| 久草精品在线观看| 美女又爽又黄视频毛茸茸| 国产精品三级av| 国产精品第一页在线观看| 欧美性xxxxxxxx| 日韩一区二区三区不卡| 精品国偷自产在线视频99| 天堂√中文最新版在线| 成人做爽爽免费视频| 欧美日韩播放| 国产精品国产对白熟妇| 另类人妖一区二区av| 国产高清自拍视频| 伊人色综合久久天天人手人婷| 激情网站在线观看| 亚洲精品久久久久久久久久久久久| 777电影在线观看| 7777精品视频| 91成人在线精品视频| 自拍另类欧美| 丝袜亚洲精品中文字幕一区| 国产免费a级片| 成人免费一区二区三区在线观看| 无码人妻丰满熟妇精品| 欧美精品一区二区久久婷婷| 巨大荫蒂视频欧美另类大| 国产精品久久久av| 欧美**vk| 成人黄色片视频| 97精品国产露脸对白| 久草成人在线视频| 91精品国产麻豆| 日本三级视频在线播放| 国产精品美女www| 国产精品亚洲片在线播放| 免费看黄在线看| 国产69精品久久久久毛片 | 国产天堂在线| 26uuu日韩精品一区二区| 麻豆一区二区麻豆免费观看| 国产精品国三级国产av| 国产成人午夜视频| 欧美日韩免费一区二区| 91精品国产欧美一区二区成人| 日本三级在线视频| 国产日韩欧美在线| 国产韩日影视精品| 一区二区三区网址| 亚洲国产成人午夜在线一区 | 高清视频在线观看三级| 超碰97国产在线| 激情成人亚洲| 在线天堂www在线国语对白| 亚洲国产视频网站| 色偷偷在线观看| 欧美一级大片在线免费观看| 亚洲专区视频| 国产三级日本三级在线播放| 国产片一区二区| 中文字幕一区二区在线视频| 有码中文亚洲精品| 欧洲精品久久久久毛片完整版| 亚洲欧美日韩精品综合在线观看| 久久国产福利国产秒拍| 91 在线视频| 欧美大片国产精品| 免费h视频在线观看| 日本成人三级电影网站| 日本vs亚洲vs韩国一区三区| 国产精品www爽爽爽| 欧美精品精品一区| 羞羞视频在线免费国产| 精品视频一区在线| 日韩电影免费在线观看网站| 一级特黄曰皮片视频| 欧美酷刑日本凌虐凌虐| 羞羞的网站在线观看| 国产欧美综合精品一区二区| 久久久噜噜噜| 一区二区视频免费看| 亚洲国产欧美一区二区三区同亚洲 | 成人综合视频在线| 国产婷婷一区二区| 国产特级黄色片| 欧美亚洲第一页| 色综合久久一区二区三区| 亚洲成年人av| 日本精品一级二级| 黄色小网站在线观看| 久久精品五月婷婷| 久久草av在线| 欧美不卡视频在线观看| 中文字幕视频在线免费欧美日韩综合在线看 | 国产在线一卡二卡| 亚洲精品视频网上网址在线观看| 国产在视频一区二区三区吞精| 美女黄色免费看| 国产精品区一区二区三区| 成人久久久精品国产乱码一区二区| 欧美怡红院视频一区二区三区| 香蕉综合视频| 国产精品亚洲无码| 日韩一区二区精品在线观看| 老司机成人影院| 日韩 欧美 视频| 国产精品视频你懂的| 五十路在线视频| 亚洲一区二区三区xxx视频| 99国产精品自拍|