精品欧美一区二区三区在线观看 _久久久久国色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ù)棧公眾號

国产成人精品影视| 成人高清电影网站| 欧美日韩加勒比精品一区| 国产三级精品在线不卡| 亚洲欧美一二三区| 国产精品黑丝在线播放| 精品福利一二区| 无码精品国产一区二区三区免费| 日韩免费啪啪| 成人国产精品免费观看视频| 国产成人亚洲综合| 69av视频在线| 精品美女在线视频| 日韩精品一区二区三区在线| 不要播放器的av网站| 污视频网站在线免费| 2022国产精品视频| 3d精品h动漫啪啪一区二区| www.国产色| 888久久久| 国产一区二区美女视频| 91精品国产高清91久久久久久| 97成人资源| 亚洲一区二区五区| 亚洲国产成人不卡| 四虎精品在线| 国产91丝袜在线18| 国产欧洲精品视频| 日韩综合在线观看| 伊人久久亚洲美女图片| 久久精品人人做人人爽| 久久久视频6r| 一本色道久久综合亚洲精品酒店 | 最近2019中文字幕在线高清| 午夜视频在线观看国产| 成人在线视频国产| 欧美亚洲免费在线一区| 欧美二区在线视频| 污片视频在线免费观看| 自拍偷拍欧美精品| 日韩在线电影一区| 理论视频在线| caoporn国产一区二区| 91视频-88av| 91精品在线视频观看| 肉丝袜脚交视频一区二区| 久久免费精品视频| 美女视频黄免费| 一区二区中文字| 色婷婷av一区二区三区在线观看| 白白色免费视频| 天天躁日日躁狠狠躁欧美巨大小说 | 欧美日韩综合一区二区三区| 99视频在线精品国自产拍免费观看| 欧美区二区三区| 久久高清内射无套| 亚洲精品在线观看91| 日韩一区二区av| 黄色精品视频在线观看| 欧美疯狂party性派对| 中文字幕av日韩| 成人信息集中地| 日韩在线观看| 久久九九国产精品怡红院| 国产精品精品软件男同| 亚洲va在线| 久热精品视频在线| 欧美精品一区二区蜜桃| 亚洲二区免费| 欧美在线免费观看| 亚洲av无码精品一区二区| 日日欢夜夜爽一区| 国产精品免费电影| 国产精品亚洲lv粉色| 国产精品一区在线观看你懂的| 亚洲a级在线播放观看| 精品女同一区二区三区| 成人中文字幕电影| 欧美大香线蕉线伊人久久国产精品| 日本亚洲一区| 国产精品女主播av| 欧美日韩中文字幕在线播放| 青草在线视频在线观看| 懂色av一区二区三区| 精品久久久久久久免费人妻| 日韩护士脚交太爽了| 日韩视频在线你懂得| 香港三级日本三级| 国产亚洲一区| 欧美超级免费视 在线| 国产无遮挡aaa片爽爽| 蘑菇福利视频一区播放| 91精品国产自产在线老师啪| 亚洲精品国产一区二| 91免费在线看| 黄色一级视频播放| 日韩av一卡| 欧美剧在线免费观看网站| 亚洲欧美日韩中文字幕在线观看| 奇米影视777在线欧美电影观看 | 精品久久久久久一区| 国产高清一区在线观看| 亚洲曰韩产成在线| 成人精品小视频| 涩爱av色老久久精品偷偷鲁| 亚洲天堂av高清| 青青草国产在线观看| 久久一区中文字幕| 99re在线观看| 在线观看免费网站黄| 五月婷婷激情综合网| 少妇一级淫免费放| 欧美91在线| 欧美精品在线视频观看| 无码人妻丰满熟妇区五十路| 丰满亚洲少妇av| 这里只有精品66| 免费电影日韩网站| 亚洲成人精品视频在线观看| 亚洲欧美日韩第一页| 亚洲一区欧美激情| 97人人模人人爽人人喊38tv| av影片在线看| 婷婷综合另类小说色区| 992kp免费看片| 欧美日韩水蜜桃| 777国产偷窥盗摄精品视频| 国产毛片毛片毛片毛片毛片| 国产无遮挡一区二区三区毛片日本| 国产乱子伦精品视频| 亚洲老司机网| 亚洲天堂av在线播放| 午夜精品久久久久久久久久久久久蜜桃 | 中文字幕巨乱亚洲| 免费黄色福利视频| 九色丨蝌蚪丨成人| 欧美激情精品久久久久久久变态| 国产一区二区三区成人| 国产日韩精品一区二区浪潮av | 亚洲成人在线视频播放| 国产人妻精品一区二区三区不卡| 日本午夜一区二区| 欧美日韩亚洲在线| 一区二区三区四区日本视频| 日韩成人在线视频观看| 日本一级黄色大片| 成人综合在线观看| 久久天天东北熟女毛茸茸| 亚洲一区二区三区久久久| 伊人久久五月天| 国产免费www| 久久久久高清精品| 日韩av播放器| 欧美最新另类人妖| 国产精品自在线| www.亚洲免费| 欧美少妇一区二区| 精品国产大片大片大片| 精品一区二区三区的国产在线播放| 一级日韩一区在线观看| 性欧美video另类hd尤物| 色播久久人人爽人人爽人人片视av| 高潮无码精品色欲av午夜福利| 国产午夜精品一区二区| 欧美成人三级在线播放| 五月精品视频| 福利精品视频| 97超碰在线免费| 国产视频久久久久| 欧美日韩 一区二区三区| 欧美国产1区2区| 亚洲图色中文字幕| 欧美1区2区视频| 国模精品一区二区三区| 肉色欧美久久久久久久免费看| 一区二区在线视频| 97精品人妻一区二区三区| 亚洲精品日产精品乱码不卡| 美女露出粉嫩尿囗让男人桶| 99伊人成综合| 日韩久久精品一区二区三区| 日本a人精品| 欧美大片在线影院| 免费成人av电影| 欧美日本韩国一区二区三区视频| 欧美日韩精品亚洲精品| 久久综合色鬼综合色| 在线观看亚洲色图| 黄色一区二区三区四区| 日韩精品欧美一区二区三区| 欧美一区一区| 日韩女优人人人人射在线视频| 欧美极品视频| 精品网站999www| 国产精品久久免费| 五月综合激情婷婷六月色窝| 成人免费视频入口| 成人听书哪个软件好| 一区二区成人网| 精品成人国产| 亚洲一区二区三区在线观看视频| 91成人精品在线| 国产精品免费网站| av日韩中文| 久久手机免费视频| 欧美孕妇性xxxⅹ精品hd| 欧美一区二区三区啪啪| 国产毛片aaa| 亚洲欧美日韩在线播放| 日本黄色动态图| 国产一区视频导航| 国产情侣av自拍| 精品成人一区| 天天综合五月天| 国产乱码精品一区二区亚洲 | 涩涩屋成人免费视频软件| 国产成人免费91av在线| jizz一区二区三区| 久久久成人的性感天堂| 国产精品久久久久一区二区国产 | 浪潮av一区| 国产亚洲精品成人av久久ww| 欧美一级淫片免费视频魅影视频| 91精品国产乱码久久蜜臀| 99re这里只有精品在线| 天天综合色天天综合色h| 精品欧美一区二区久久久久| 欧美国产一区二区在线观看| 一区二区三区免费在线观看视频| 粉嫩蜜臀av国产精品网站| 天天干天天色天天干| 日韩精品亚洲专区| 成人免费在线小视频| 亚洲视频一二| 久久这里只有精品8| 亚洲欧美综合久久久| 伊人久久大香线蕉av一区| 国产在线日韩精品| 欧美亚洲另类在线一区二区三区| 久久资源综合| 国产专区一区二区| 久久国产精品免费精品3p| 国产日本一区二区三区| 成人动态视频| 国产精品久久久久久免费观看| 欧美经典一区| 96国产粉嫩美女| 精品一区二区三区免费看| 91久久综合亚洲鲁鲁五月天| 欧美成人三级| 亚洲va男人天堂| 久久久久亚洲精品中文字幕| 亚洲最大福利视频| 精品视频一区二区三区| 1卡2卡3卡精品视频| 亚洲精品视频一二三区| 99免费在线视频观看| 综合成人在线| 精品视频一区在线| 亚洲精品国模| 日韩亚洲视频| 国产电影一区二区在线观看| 中文字幕第一页亚洲| 亚洲成av人片一区二区密柚| 成人一区二区av| 亚洲激情偷拍| 国产精品免费成人| 毛片av一区二区三区| www.成人黄色| 国产成人高清视频| 91精品又粗又猛又爽| av电影天堂一区二区在线观看| 91黄色免费视频| 欧美国产视频在线| 18岁成人毛片| 黄色91在线观看| 欧美在线视频精品| 欧美一级精品在线| 亚洲男人第一天堂| 日韩精品有码在线观看| 2019中文字幕在线视频| 欧美成人自拍视频| 亚洲美女尤物影院| 国产精品欧美一区二区| 亚洲第一二区| 欧美久久电影| 欧美不卡高清| 最近免费中文字幕中文高清百度| 狠狠色丁香久久婷婷综合丁香| 中文字幕99页| 中文字幕第一区| 久草视频在线免费看| 一本到高清视频免费精品| 国产乱码精品一区二三区蜜臂 | 欧美亚洲尤物久久| 亚洲av永久无码国产精品久久| 亚洲欧美福利视频| 在线网址91| 国产精品白丝jk喷水视频一区| 欧美中文高清| 日本10禁啪啪无遮挡免费一区二区| 99久久久国产精品美女| 欧美成人xxxxx| 国内成人自拍视频| 美女久久久久久久久久| 亚洲日本欧美天堂| 懂色av中文字幕| 精品久久久久久亚洲综合网| 成人在线观看网站| 97国产suv精品一区二区62| 国产资源一区| 蜜桃网站成人| 国语对白精品一区二区| 午夜剧场在线免费观看| jiyouzz国产精品久久| 欧美成人777| 欧美性色综合网| 四虎影视2018在线播放alocalhost| 久久99国产精品自在自在app| 成人午夜亚洲| 日本精品二区| 西西裸体人体做爰大胆久久久| 男插女视频网站| 国产精品久久久爽爽爽麻豆色哟哟| 中文字幕在线观看免费视频| 日韩精品一区二区三区中文不卡 | 国产黄色片av| 日韩少妇与小伙激情| 日本在线视频一区二区| 好吊色欧美一区二区三区 | 中文字幕天堂在线| 亚洲精品一区二区三区在线观看| 最新国产在线拍揄自揄视频| 国产精品吴梦梦| 精品国产一区二区三区久久久蜜臀| 日本在线xxx| www.欧美日韩| 国产91av视频| 精品国产污网站| 日本电影在线观看| 福利精品视频| 欧美视频四区| 亚洲美女高潮久久久| 亚洲综合在线免费观看| 性欧美18一19性猛交| 色中色综合影院手机版在线观看| 91成人福利社区| 国产又粗又爽又黄的视频 | 日韩av无码一区二区三区不卡 | 日日狠狠久久偷偷四色综合免费 | 男女在线视频| 99热99热| 亚洲人成在线影院| 亚洲精品在线视频免费观看| 欧美日韩一区二区精品| 视频二区在线| 国产精品电影网| 精品免费av| 久久精品国产99久久99久久久| 亚洲精品国产成人久久av盗摄| www.久久精品.com| 国模精品系列视频| 丝袜久久网站| 99视频精品免费| 中文字幕一区二区不卡| 国产免费高清av| 欧美丰满老妇厨房牲生活 | 国产在线不卡一区| 欧美日韩综合一区二区| 精品国产一区二区三区久久影院 | 香港三级日本三级| 日本韩国视频一区二区| av大片在线观看| 91精品久久久久久久久青青| 综合精品久久| 加勒比精品视频| 欧洲亚洲国产日韩| 国产日产一区二区| 国产精品视频一区二区三区经| 一本一本久久| 国产黄色片在线| 精品乱码亚洲一区二区不卡| jizz内谢中国亚洲jizz| 亚洲一区二区在| 成人做爰69片免费看网站| 国产成人精品777777| 精品国内产的精品视频在线观看| 亚洲精品一区二区三区中文字幕| 婷婷五月综合缴情在线视频| 国产欧美日韩在线看| 精品人妻一区二区三区四区不卡 | 成年丰满熟妇午夜免费视频| 91在线看国产| 91麻豆成人精品国产| 91av福利视频| 亚洲电影影音先锋| 五月开心播播网| 日韩无一区二区| 日本韩国欧美| av在线观看地址|