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

Javascript 多線(xiàn)程編程的前世今生

開(kāi)發(fā) 開(kāi)發(fā)工具
Javascript 不是單線(xiàn)程的嗎?Javascript IO 阻塞和其他異步的需求(例如 setTimeout, Promise, requestAnimationFrame, queueMicrotask 等)不是通過(guò)事件循環(huán)(Event Loop)來(lái)解決的嗎?

 作者:jolamjiang,騰訊 WXG 前端開(kāi)發(fā)工程師

一篇關(guān)于 Web Worker、SharedArrayBuffer、Atomics 的文章。

[[330324]]

為什么要多線(xiàn)程編程

大家看到文章的標(biāo)題《Javascript 多線(xiàn)程編程》可能立馬會(huì)產(chǎn)生疑問(wèn):Javascript 不是單線(xiàn)程的嗎?Javascript IO 阻塞和其他異步的需求(例如 setTimeout, Promise, requestAnimationFrame, queueMicrotask 等)不是通過(guò)事件循環(huán)(Event Loop)來(lái)解決的嗎?

沒(méi)有錯(cuò),Javascript 的確是單線(xiàn)程的,阻塞和其他異步的需求的確是通過(guò)實(shí)現(xiàn)循環(huán)來(lái)解決的,但是這套機(jī)制當(dāng)線(xiàn)程需要處理大規(guī)模的計(jì)算的時(shí)候就不大適用了,試想一下一下的場(chǎng)景:

  1. 你需要實(shí)現(xiàn)對(duì)文件的加解密。
  2. 你的 VirtualDom 樹(shù)有很多元素(例如上萬(wàn)個(gè)),你需要對(duì)這棵樹(shù)進(jìn)行 Diff 操作。
  3. 你需要在瀏覽器“挖礦”。

上面這些場(chǎng)景都會(huì)阻塞主線(xiàn)程,也就是當(dāng)進(jìn)行這些操作的時(shí)候,你的頁(yè)面是卡住的,設(shè)置當(dāng)頁(yè)面卡住一段時(shí)間之后,Chrome 等瀏覽器或者操作系統(tǒng)會(huì)建議你 Kill 掉整個(gè) Tab 或者進(jìn)程。這顯然不是我們想看到的事情。正因?yàn)檫@些場(chǎng)景的存在,瀏覽器提出了 W3C 在 2013 年提出了 Web Worker 草案,這個(gè)草案的提出就是為了解決上述這些問(wèn)題。

為了讓大家感受 JS 多線(xiàn)程能夠干什么,筆者寫(xiě)了一個(gè)基于 Web Worker(線(xiàn)程)、ShareArrayBuffer(共享內(nèi)存)、Atomics(鎖)等 Web API 的在前端壓縮和解壓文件(基于 DEFLATE 算法)的 demo:

Web Worker

Chrome 瀏覽器中每個(gè) Tab 都是一個(gè)進(jìn)程,每個(gè)進(jìn)程都會(huì)有一個(gè)主線(xiàn)程,網(wǎng)頁(yè)的渲染(Style, Layout, Paint, Composite)會(huì)在主線(xiàn)程進(jìn)行操作。主線(xiàn)程可以發(fā)起多個(gè) Web Worker,Web Worker 對(duì)應(yīng)“線(xiàn)程”的概念。

 

每個(gè) Web Worker 都對(duì)應(yīng)一個(gè)腳本文件,主線(xiàn)程可以通過(guò)像以下的代碼去發(fā)起多個(gè) Web Worker,并且通過(guò)基于事件的 API 與 Web Worker 通信:

main.js

  1. let worker = new Worker("work.js"); 
  2. worker.postMessage("Hello World"); 
  3. worker.onmessage = function (event) { 
  4.   console.log("Received message " + event.data); 

Web Worker 也通過(guò)相應(yīng)的實(shí)現(xiàn) API 與主線(xiàn)程進(jìn)行通信

worker.js

  1. this.addEventListener("message"function (e) { 
  2.   this.postMessage("You said: " + e.data); 
  3. }, false); 

Web Worker 通訊的效率與同步問(wèn)題

主線(xiàn)程與 Web Worker 通過(guò) postMessage(data: any) 通信的時(shí)候,data 會(huì)先被 copy 一份再傳給 Web Worker;同樣地,當(dāng) Web Worker 通過(guò) postMessage(data: any) 與主線(xiàn)程通信的時(shí)候,data 也會(huì)同樣先被 copy 一份再傳給主線(xiàn)程。

 

這樣做顯然會(huì)導(dǎo)致通信上的效率問(wèn)題,試想一下你需要在 Web Worker 里面解壓一個(gè) 1G 大小的問(wèn)題,你需要把整個(gè) 1G 的文件 copy 到 Web Worker 里,Web Worker 解壓完這個(gè) 1G 文件后,再把解壓完的文件 copy 回主線(xiàn)程里。

SharedArrayBuffer

為了解決通訊效率問(wèn)題,瀏覽器提出了 ShareArrayBuffer,ShareArrayBuffer 基于 ArrayBuffer 和 TypedArray API。ArrayBuffer 對(duì)應(yīng)一段內(nèi)存(二進(jìn)制內(nèi)容),為了操作這段內(nèi)存,瀏覽器需要提供一些視圖(Int8Array 等),例如可以把這段內(nèi)存當(dāng)做每 8 位一個(gè)單元的 byte 數(shù)組,每 16 位一個(gè)單元的 16 位有符號(hào)數(shù)數(shù)組。

 

注意:ArrayBuffer 中的二進(jìn)制流被翻譯成各種視圖的時(shí)候采用小端還是大端是由具體硬件決定的,絕大部分情況下是采用小端字節(jié)順序。

這段內(nèi)存可以在不同的 Worker 之間共享,但是內(nèi)存的共享又會(huì)產(chǎn)生另外的問(wèn)題,也就是競(jìng)爭(zhēng)的問(wèn)題(race onditions):

計(jì)算機(jī)指令對(duì)內(nèi)存操作進(jìn)行運(yùn)算的時(shí)候,我們可以看做分兩步:一是從內(nèi)存中取值,二是運(yùn)算并給某段內(nèi)存賦值。當(dāng)我們有兩個(gè)線(xiàn)程對(duì)同一個(gè)內(nèi)存地址進(jìn)行 +1 操作的時(shí)候,假設(shè)線(xiàn)程是先后順序運(yùn)行的,為了簡(jiǎn)化模型,我們可以如下圖表示:

 

上面兩個(gè)線(xiàn)程的運(yùn)行結(jié)果也符合我們的預(yù)期,也即線(xiàn)程分別都對(duì)同一地址進(jìn)行了 +1 操作,最后得到結(jié)果 3。但因?yàn)閮蓚€(gè)線(xiàn)程是同時(shí)運(yùn)行的,往往會(huì)發(fā)生下圖所表示的問(wèn)題,也即讀取與寫(xiě)入可能不在一個(gè)事務(wù)中發(fā)生:

 

這種情況就叫做競(jìng)爭(zhēng)問(wèn)題(Race Condition)。

Atomics

為了解決上述的競(jìng)爭(zhēng)問(wèn)題,瀏覽器提供了 Atomics API,這組 API 是一組原子操作,可以將讀取和寫(xiě)入綁定起來(lái),例如下圖中的 S1 到 S3 操作就被瀏覽器封裝成 Atomics.add() 這個(gè) API,從而解決競(jìng)爭(zhēng)問(wèn)題。

 

Atomics API 具體包含:

  • Atomics.add()
  • Atomics.and()
  • Atomics.compareExchange()
  • Atomics.exchange()
  • Atomics.isLockFree()
  • Atomics.load()
  • Atomics.notify()
  • Atomics.or()
  • Atomics.store()
  • Atomics.sub()
  • Atomics.wait()
  • Atomics.xor()

有了這套 API,我們可以實(shí)現(xiàn)像 Golang 中的 Golang Synchronization Primitives 的功能。Mutex 和 Cond 的實(shí)現(xiàn)會(huì)在下面介紹。

WebAssembly

有了 SharedArrayBuffer 和 Atomics 能力之后,證明瀏覽器能夠提供內(nèi)存共享和鎖的實(shí)現(xiàn)了,也就是說(shuō) WebAssembly 線(xiàn)程在瀏覽器機(jī)制上能夠高效地得到保證。

其實(shí)我嚴(yán)重懷疑 SharedArrayBuffer 和 Atomics 是為了支持 WebAssembly 才把 API 順便提供給 JS Runtime 的,因?yàn)槟壳盀橹箾](méi)有看到 ES 有比較豐富的關(guān)于鎖的草案(例如像 Java 中的 synchronized 關(guān)鍵字)。

Mutext 和 Cond 的實(shí)現(xiàn)

上面提到了,基于 ShareArrayBuffer 和 Atomics 可以開(kāi)發(fā)像 Golang Synchronization Primitives 一樣的 API,下面介紹一下 Mutex 和 Cond 的實(shí)現(xiàn)。實(shí)現(xiàn)的介紹是基于 Mozzila Javascript 編譯器工程師 Lars T Hansen 實(shí)現(xiàn)關(guān)于鎖的庫(kù)。

Mutex

首先說(shuō)一下 Mutex 的功能,Mutex 的 API 大概是這樣的:

  1. let mutex = new Lock(shareArrayBuffer, ...); 
  2. mutex.lock(); 
  3. doSomething(); 
  4. mutex.unlock(); 

Mutex 可以保證 lock() 和 unlock() 之間的代碼代碼不會(huì)被打斷。下面是介紹具體實(shí)現(xiàn):

首先定義 Mutex 的三個(gè)狀態(tài)以及對(duì)應(yīng)的狀態(tài)機(jī)

  • UNLOCK: 未鎖定
  • LOCKED: 被鎖定
  • WAITED: 被鎖定且大于等于 1 個(gè)線(xiàn)程在等待該鎖

 

對(duì)于 Worker 線(xiàn)程來(lái)說(shuō) Mutex 的每個(gè)狀態(tài)都可能是初始態(tài),狀態(tài)與狀態(tài)間扭轉(zhuǎn)會(huì)產(chǎn)生一些操作且進(jìn)入下一狀態(tài):

加鎖 lock()

  • 初始狀態(tài)為UNLOCK: 鎖未被搶占,將狀態(tài)扭轉(zhuǎn)為 LOCKED,線(xiàn)程進(jìn)行后續(xù)操作。
  • 初始狀態(tài)為L(zhǎng)OCKED: 鎖已被搶占,將狀態(tài)扭轉(zhuǎn)為 WAITED,并將線(xiàn)程設(shè)置為等待態(tài),并將線(xiàn)程設(shè)置為當(dāng)鎖的狀態(tài)不為 WAITED 的時(shí)候可能被喚醒,一旦被喚醒則該線(xiàn)程擁有鎖,線(xiàn)程進(jìn)行后續(xù)操作。
  • 初始狀態(tài)為WAITED: 鎖已被搶占,并將線(xiàn)程設(shè)置為等待態(tài),并將線(xiàn)程設(shè)置為當(dāng)鎖的狀態(tài)不為 WAITED 的時(shí)候可能被喚醒,一旦被喚醒則該線(xiàn)程擁有鎖,線(xiàn)程進(jìn)行后續(xù)操作。

釋放 unlock()

1.初始狀態(tài)為L(zhǎng)OCKED: 鎖被搶占且未被等待,將狀態(tài)扭轉(zhuǎn)為 UNLOCK,線(xiàn)程進(jìn)行后續(xù)操作。

2.初始狀態(tài)為WAITED: 鎖被搶占且被等待,將狀態(tài)扭轉(zhuǎn)為 LOCKED,喚醒一個(gè)在等待態(tài)的線(xiàn)程,線(xiàn)程進(jìn)行后續(xù)操作。

上面描述的邏輯的對(duì)應(yīng)的代碼如下:

  1. // lock 
  2. Lock.prototype.lock = function () { 
  3.   const iab = this._iab; 
  4.   const stateIdx = this._ibase; 
  5.   let c; 
  6.   if ((c = Atomics.compareExchange(iab, stateIdx, 0, 1)) != 0) { 
  7.     do { 
  8.       if (c == 2 || Atomics.compareExchange(iab, stateIdx, 1, 2) != 0) 
  9.         Atomics.wait(iab, stateIdx, 2); 
  10.     } while ((c = Atomics.compareExchange(iab, stateIdx, 0, 2)) != 0); 
  11.   } 
  12.  
  13. // unlock 
  14. Lock.prototype.unlock = function () { 
  15.     const iab = this._iab; 
  16.     const stateIdx = this._ibase; 
  17.     let v0 = Atomics.sub(iab, stateIdx, 1); 
  18.     // Wake up a waiter if there are any 
  19.     if (v0 != 1) { 
  20.         Atomics.store(iab, stateIdx, 0); 
  21.         Atomics.notify(iab, stateIdx, 1); 
  22.     } 

可以看到鎖的實(shí)現(xiàn)用到了 Atomics.compareExchange() 和 Atomics.wait()(相當(dāng)于 Linux 中的 futex)兩個(gè)原子操作。

Cond

Cond 是基于 Mutex 實(shí)現(xiàn)的,它的大致功能是持有鎖的情況下可進(jìn)行兩種操作:

  • wait(): 本線(xiàn)程進(jìn)度進(jìn)入等待態(tài),并且被喚醒的時(shí)候重新持有鎖。
  • notifyOne(): 喚醒一個(gè)正在等待態(tài)的線(xiàn)程。

具體使用方法如下:

  1. // thread A 
  2. var msg = new Int32Array(sab, msgLoc, 1); 
  3. lock.lock(); 
  4. while (msg[0] < numWorkers) 
  5.  cond.wait(); 
  6. lock.unlock(); 
  7.  
  8. // thread B, C, D, E, … 
  9. var msg = new Int32Array(sab, msgLoc, 1); 
  10. lock.lock(); 
  11. msg[0]++; 
  12. cond.notifyOne(); 
  13. lock.unlock(); 

由于 Cond 是基于 Mutex,前置條件是持有鎖,后置條件是釋放鎖,你可以看做 Cond 只有兩個(gè)狀態(tài):

  • NORMAL: 非等待態(tài),調(diào)用 wait() 轉(zhuǎn)化為 WAITED 狀態(tài),并把線(xiàn)程設(shè)置為等待態(tài),并且被喚醒的時(shí)候重新持有鎖,然后進(jìn)行后續(xù)操作。
  • WAITED: 等待態(tài)(不對(duì)應(yīng)上述 Lock 的 WAITED 態(tài)),調(diào)用 notifyOne() 將狀態(tài)設(shè)置為 NORMAL 態(tài),重新喚醒一個(gè)處于等待態(tài)的線(xiàn)程,然后進(jìn)行后續(xù)操作。

 

異步鎖

上述介紹的鎖都是同步的,Atomics.wait 不能在主線(xiàn)程使用,在主線(xiàn)程使用的話(huà)瀏覽器會(huì)拋出異常:

  1. Uncaught TypeError: Atomics.wait cannot be called in this context 

所以我們需要設(shè)計(jì)所謂的”異步鎖“,所謂的異步鎖原理很簡(jiǎn)單,就是將同步鎖里面的 Atomics.wait() 操作交給一個(gè)新的線(xiàn)程,主線(xiàn)程和這個(gè)線(xiàn)程通過(guò)事件通信來(lái)異步化這里的操作。具體實(shí)現(xiàn)可以參照這個(gè)文件)。

demo 實(shí)現(xiàn)

介紹完上述的知識(shí)之后,就可以用相關(guān)的 API 就可以實(shí)現(xiàn)我們的 demo 了,首先畫(huà)一下我們 demo 的架構(gòu)圖:

 

如圖所示,在線(xiàn)解壓縮這個(gè) demo 主要分為兩個(gè)線(xiàn)程:

主線(xiàn)程:負(fù)責(zé)調(diào)用 Dom API 等,主要負(fù)責(zé) UI 更新。

工作線(xiàn)程:負(fù)責(zé)文件的壓縮/解壓。

兩個(gè)線(xiàn)程間的通信是通過(guò)讀寫(xiě)兩段共享內(nèi)存來(lái)實(shí)現(xiàn)的,對(duì)于共享內(nèi)存的訪問(wèn),通過(guò)鎖來(lái)解決競(jìng)爭(zhēng)問(wèn)題。需要注意的是,主線(xiàn)程的寫(xiě)緩存也即工作線(xiàn)程的讀緩存,反之亦然。

demo 的具體實(shí)現(xiàn)可以參照 demo 的 Github 地址。

目前多線(xiàn)程編程的不足

目前只通過(guò)瀏覽器提供的 API 來(lái)進(jìn)多線(xiàn)程開(kāi)發(fā)的話(huà)成本非常大,主要有兩方面問(wèn)題:

過(guò)于底層的 API

1.需要你實(shí)現(xiàn)語(yǔ)言級(jí)、或者系統(tǒng)級(jí)的 lock API,參照 Golang 的 lock API。

2.沒(méi)有語(yǔ)法上的支持,例如 Java synchronized 關(guān)鍵字等。

普通的 Javascript Object 無(wú)法共享

這其實(shí)也是 API 過(guò)于底層的另一方面的體現(xiàn),也就是說(shuō)對(duì) JS 對(duì)象進(jìn)行內(nèi)存共享的話(huà),你需要開(kāi)辟一段 SharedArrayBuffer,然后在此之上實(shí)現(xiàn)對(duì) JS 對(duì)象的序列化、反序列化、更新等操作,實(shí)現(xiàn)成本也是比較大的。

事實(shí)上我們也不應(yīng)該輕易手動(dòng)實(shí)現(xiàn)相關(guān)的庫(kù)或者功能,因?yàn)橄嚓P(guān)領(lǐng)域的問(wèn)題非常復(fù)雜、需要仔細(xì)的設(shè)計(jì)和實(shí)現(xiàn)。例如我們可以先使用下面這兩個(gè)庫(kù):

  1. parlib-simple: 這個(gè)庫(kù)里面有類(lèi)似于 Golang 里面 channel 一樣的 API。
  2. js-lock-and-condition: 這里庫(kù)有 Mutex 和 Cond 實(shí)現(xiàn)。

總結(jié)

瀏覽器提供給了我們進(jìn)行多線(xiàn)程的能力,例如 PWA 或者 WebAseembly 與 JS 混用等場(chǎng)景都會(huì)用到上述的機(jī)制,如果你想實(shí)現(xiàn)一個(gè)高性能的網(wǎng)頁(yè)客戶(hù)端程序(例如 Figma 一樣的殺手級(jí)應(yīng)用),你最好也用上上述的機(jī)制。值得注意的是,用了鎖可能會(huì)降低你的程序的性能,具體要看線(xiàn)程切換和等待是的成本是否能夠抵消內(nèi)存拷貝的成本,例如 demo 完全可以改成無(wú)鎖的,代價(jià)將文件內(nèi)容拷貝到共享線(xiàn)程,并把工作線(xiàn)程的內(nèi)容拷貝回主線(xiàn)程。

雖然上面建議不要輕易實(shí)現(xiàn)自己的庫(kù),例如上面的 lock 代碼短短幾行,但是其中的推導(dǎo)可以足夠?qū)懯畮醉?yè)的 Paper 了,但是這里的基礎(chǔ)能力很匱乏,據(jù)筆者了解,TC39 提案中鮮少出現(xiàn)關(guān)于多線(xiàn)程編程的提案,目前僅發(fā)現(xiàn)以下這個(gè):

  1. proposal-atomics-wait-async 

但是,如果自信有能力和時(shí)間建設(shè)這些基礎(chǔ)能力的話(huà),這個(gè)領(lǐng)域的確是“廣闊天地,大有作為”,特別是如果你的項(xiàng)目準(zhǔn)備用 WebAseembly 和 JS 混用的情況(例如 Figma 就是用了 WebAssembly 和 React)。

 

責(zé)任編輯:武曉燕 來(lái)源: 51CTO
相關(guān)推薦

2019-08-05 10:08:25

軟件操作系統(tǒng)程序員

2011-08-23 09:52:31

CSS

2014-07-30 10:55:27

2015-11-18 14:14:11

OPNFVNFV

2025-02-12 11:25:39

2021-05-31 20:06:57

網(wǎng)元協(xié)議網(wǎng)關(guān)

2012-05-18 16:54:21

FedoraFedora 17

2019-06-04 09:00:07

Jenkins X開(kāi)源開(kāi)發(fā)人員

2013-05-23 16:23:42

Windows Azu微軟公有云

2014-07-15 10:31:07

asyncawait

2021-06-17 07:08:19

Tapablewebpack JavaScript

2016-12-29 18:21:01

2014-07-21 12:57:25

諾基亞微軟裁員

2016-12-29 13:34:04

阿爾法狗圍棋計(jì)算機(jī)

2016-11-03 13:33:31

2016-11-08 19:19:06

2013-11-14 16:03:23

Android設(shè)計(jì)Android Des

2021-04-15 07:01:28

區(qū)塊鏈分布式DLT

2011-05-13 09:43:27

產(chǎn)品經(jīng)理PM

2022-11-07 14:23:35

RPA人工智能流程自動(dòng)化管理
點(diǎn)贊
收藏

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

黄色网址在线视频| 欧美精品videosex| 自拍亚洲欧美老师丝袜| 亚洲精品美腿丝袜| 88xx成人免费观看视频库| 欧美激情第3页| 日韩欧美综合一区| 96sao在线精品免费视频| 国产一精品一aⅴ一免费| 日韩va亚洲va欧洲va国产| 亚洲黄色录像| 手机看片国产日韩| 茄子视频成人在线| 国产在线看一区| 神马久久精品| 中国老女人av| 欧美性色黄大片| 久9re热视频这里只有精品| 麻豆视频免费在线播放| 欧美精品aaa| 日本欧美一区二区三区| 亚洲黄色精品视频| 日韩欧美在线一区二区| 亚洲va国产va欧美va观看| 高清电影一区| 国内精品久久99人妻无码| 欧美日韩不卡合集视频| 精品一区二区在线看| 欧洲天堂在线观看| av在线无限看| 伊人成人开心激情综合网| 亚洲视频狠狠| 亚洲大尺度视频| 糖心vlog在线免费观看| 91麻豆精品国产91久久久| 天天射综合网视频| 亚洲第一免费视频| 国产 日韩 欧美在线| 日韩亚洲欧美中文三级| 亚洲网站在线| 天堂在线观看av| 少妇高潮喷水在线观看| 一本大道久久加勒比香蕉| 免费一级欧美片在线观看| 久久久久久久久亚洲精品| 久草资源站在线观看| 亚洲免费视频在线观看| 免费不卡在线观看| a视频在线播放| 四虎成人在线播放| 国内精品免费午夜毛片| 国产日产欧美一区二区三区| 久久影院资源站| 一级特黄曰皮片视频| 91视频免费在线观看| 五月天中文字幕一区二区| 日韩精品首页| 色视频在线观看福利| 老司机av网站| 91精品视频在线| 欧美视频一区二区三区四区| 亚洲午夜精品久久久久久app| jizz在线观看中文| 在线不卡av电影| 美日韩免费视频| 精品av久久707| 白白色 亚洲乱淫| 亚洲91网站| www.我爱av| 超级砰砰砰97免费观看最新一期| 国产欧美亚洲视频| 欧美一区二区三区不卡| 久久精品免费观看| 四虎视频在线精品免费网址| 7777久久亚洲中文字幕| 亚洲精品久久久久久宅男| 国产精品亚洲自拍| 欧美精品日韩精品| 大胆亚洲人体视频| 色狼人综合干| 粉嫩av一区| 欧美精品videos极品| 一本—道久久a久久精品蜜桃| 久久福利视频导航| 午夜视频一区二区三区| 日韩国产在线观看| 日韩08精品| 欧美人体大胆444www| 波多野结衣家庭教师在线观看 | 成人无号精品一区二区三区| 91精品国产综合久久久久久豆腐| 日本福利片在线观看| avav在线播放| 国产精品入口日韩视频大尺度| 制服丝袜亚洲精品中文字幕| 不卡电影一区二区三区| 久久精品99久久无色码中文字幕| 青草视频在线免费直播| 中国黄色一级视频| 亚洲中文字幕无码一区| 欧美日韩一级在线| 日韩av电影在线免费播放| 亚洲第一精品电影| 国产调教视频一区| 美女视频一区免费观看| 欧美精品一区二区久久| 国产一区高清| 久草成色在线| 精彩国产在线| 一级特黄特色的免费大片视频| 欧美性生交大片| 肉丝美足丝袜一区二区三区四| 国产欧美在线视频| 97国产精品免费视频| 午夜一区二区三区在线观看| 日本不卡一区二区| 国内精品视频在线观看| 456亚洲精品成人影院| 日韩美女一级视频| 亚洲不卡在线视频| 毛片aaaaaa| 国产成人无码av在线播放dvd| 成人免费视频观看视频| 97精品在线视频| 日韩美女av在线| 欧美丝袜第三区| 亚洲图片有声小说| 久久精品这里都是精品| 美腿丝袜亚洲三区| 欧美日韩国产一区精品一区| 欧美黄色网视频| 成人免费视频观看| 成人影院在线视频| 日本中文字幕伦在线观看| 国产1区在线观看| 国产日产精品一区二区三区| 战狼4完整免费观看在线播放版| 中文字幕av一区二区三区人妻少妇 | 欧美四级电影在线观看| 视频一区二区国产| 超碰在线亚洲| 天堂a中文在线| 黄色免费av网站| 老司机av网站| 毛葺葺老太做受视频| 成人免费淫片aa视频免费| 日韩电影大片中文字幕| 1024亚洲合集| 国产综合一区二区| 成人情趣视频| 成人国产精品入口免费视频| 污污视频在线| 色三级在线观看| 精品美女视频在线观看免费软件| 国产精品一区二区黑人巨大| 久久精品99久久久久久| 北条麻妃在线观看视频| 三上悠亚影音先锋| avtt香蕉久久| 精品国产人妻一区二区三区| 精品人妻一区二区三区免费| 日本中文字幕观看| 一区二区三区 日韩| 男女视频在线看| 国产无遮挡猛进猛出免费软件| 91猫先生在线| 国产黄色特级片| 亚洲36d大奶网| 小泽玛利亚视频在线观看| 国产一伦一伦一伦| 97超碰人人看| 污污免费在线观看| 天堂久久久久久| caopeng视频| 丁香六月激情综合| 欧洲第一无人区观看| 校园春色 亚洲| 黄色片视频网站| 中文字幕有码视频| www.色亚洲| 国产一区二区三区福利| 免费在线看黄色| 人妖欧美1区| 网友自拍亚洲| 欧洲一区在线| 欧美人与物videos另类xxxxx| 成人羞羞在线观看网站| 欧美1区2区3区| 麻豆成人在线| 国产福利视频一区二区三区| 久久久久久久综合色一本| 18成人在线观看| 色94色欧美sute亚洲线路二 | 91亚洲永久免费精品| 成人免费观看网站| 一本色道婷婷久久欧美| 日韩少妇内射免费播放| 黄色片免费网址| 四虎永久免费在线观看| 国产精品1234区| 97超碰国产在线| 日韩在线观看www| 99久久精品一区二区成人| 福利在线一区| 欧美视频久久| 国产精品系列在线播放| 国产精品久久精品日日| 日本高清不卡aⅴ免费网站| 亚洲第一中文字幕| 91av视频在线| 日本精品一区二区三区视频| 日日摸日日碰夜夜爽无码| 亚洲AV无码久久精品国产一区| 91香蕉国产视频| 伊人精品一区二区三区| 麻豆av在线免费看| 95精品视频| 国内精品久久久久久久影视麻豆| 国产激情一区二区三区四区| 亚洲视频网在线直播| 欧美va亚洲va香蕉在线| 国内偷自视频区视频综合| 激情久久av| 冲田杏梨av在线| 国产精品丝袜一区二区| 欧美 日韩 人妻 高清 中文| 日韩精品极品| 99视频精品视频高清免费| 国产成人在线免费观看| 午夜影视日本亚洲欧洲精品| 亚洲欧洲一区二区三区久久| 91精品国产综合久久香蕉最新版| 秋霞在线一区二区| 日本欧美黄色片| 国产白丝袜美女久久久久| 亚洲妇女无套内射精| 欧美性猛交bbbbb精品| 91网在线播放| 亚洲人成网亚洲欧洲无码| 美日韩一区二区| 欧美日韩精品在线视频| 色综合视频网站| 亚洲 国产 欧美一区| 国产高清成人久久| 国产日韩一级片| 欧美美女日韩| 宅男噜噜噜66一区二区| 亚洲日本一区二区三区| 这里精品视频免费| 欧美成人第一区| 亚洲一区二区在线免费| 国产高清免费av| 国产va免费精品观看精品| 欧美aaa在线| 91成人免费网站| 欧美诱惑福利视频| 99精品人妻少妇一区二区| 国产一级在线免费观看| 99riav视频在线观看| 精品91在线| 五月天视频一区| 日韩av三级在线观看| 午夜精品久久久内射近拍高清| 日韩黄色a级片| 日韩久久一区二区三区| 日韩av不卡在线观看| 欧美在线观看一二区| 国产精品视频白浆免费视频| 97超碰成人在线| va婷婷在线免费观看| 91精品日本| 91麻豆福利精品推荐| 亚洲色图17p| 国产又粗又大又爽的视频| 久久免费视频6| 永久免费毛片在线播放| 日韩激情av在线| 在线不卡a资源高清| 国产乱码精品一区二区三区中文 | 色综合久久综合网欧美综合网| 日韩av电影手机在线| 污视频在线观看免费网站| 国产香蕉在线观看| 欧美日韩国产高清电影| 亚洲精品成人天堂一二三| 91成人精品网站| 天天看片天天操| 久草视频视频在线播放| 欧美涩涩网站| 欧美精选午夜久久久乱码6080| 国产欧美一区二区三区不卡高清| 性猛交娇小69hd| 蜜桃视频www网站在线观看| 九九国产精品视频| 亚洲精品综合久久中文字幕| 正在播放久久| 中文字幕黄色av| 久久av影视| 色婷婷综合久色| 国产精品一区二区三区免费| 成人免费毛片东京热| 日韩美女在线| 国产精品丝袜91| 国产中文字幕91| 国产三级aaa| 欧美一级在线| 亚洲欧美一区二区三区久本道91 | 久久九九热免费视频| 91香蕉视频污版| 在线观看h片| 免费在线观看一区二区三区| 国产亚洲xxx| 亚洲激情在线观看视频| 日本在线观看网站| 精品午夜久久福利影院| 蜜臀久久99精品久久久无需会员 | 一区二区三区四区五区精品| 成人黄色三级视频| 色婷婷色综合| 精品免费日韩av| 国产黄色一级网站| 成年人在线看| 国产成人精品一区二区三区四区| 欧美老妇交乱视频| 四虎影成人精品a片| 一区二区三区欧洲区| 国产激情91久久精品导航| 欧美一级视频在线观看| 国产极品国产极品| 欧美超碰在线| 亚洲欧美aⅴ...| 正在播放精油久久| 三区四区电影在线观看| 欧美高清在线一区二区| 欧洲精品在线一区| 青草久久伊人| 久久久久久一级片| 涩涩日韩在线| 免费人成在线观看播放视频| 国产精品国产三级国产普通话蜜臀| 日韩少妇中文字幕| av免费观看一区二区| 国产精品麻豆99久久久久久| 欧美日韩精品免费观看视一区二区| 国产精品国产高清国产| 91麻豆国产自产在线观看| 欧美综合激情| 欧美日韩视频在线播放| 亚洲中国最大av网站| 1024精品视频| 黄色日韩网站| 日韩欧美国产精品一区| 免费无码一区二区三区| 精品国产aⅴ| 久久99久久99精品免观看粉嫩| 国产乡下妇女做爰视频| 日韩精品成人一区二区三区| 91亚洲国产成人精品性色| 日本黄色大片视频| 国产精品久99| 欧美日韩亚洲一| 成人在线日韩| 亚洲美女av黄| 日本五十熟hd丰满| 久久99深爱久久99精品| 久久本道综合色狠狠五月| 久草免费在线| 国产精品一区二区三区乱码| 茄子视频成人在线观看| 欧美性受ⅹ╳╳╳黑人a性爽| 欧美影院午夜播放| 受虐m奴xxx在线观看| 国产一区白浆| 国产精品视频成人| av图片在线观看| 成人动漫一区二区在线| 波多野结衣激情| 日韩深夜福利网站| 亚洲国产一区二区a毛片| 一本之道在线视频| 99久久久久国产精品| 国产精品对白刺激| 好男人免费精品视频| 精品久久久国产| 800av在线播放| 国产欧美精品久久| 久久久久久久久久久久久久久久av| 手机在线免费观看av| 亚洲午夜激情av| www黄色av| 日韩成人影音| 在线欧美小视频| 国产尤物av一区二区三区| 免费a在线看| 国产精品久久综合| 亚洲一区二区三区涩| 日本中文字幕在线看| 国产精品国产a| 国产aaaaa毛片| 国产精品av一区二区|