欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

Python進(jìn)程和線程知識(shí)點(diǎn)舉例分析

本篇內(nèi)容主要講解“Python進(jìn)程和線程知識(shí)點(diǎn)舉例分析”,感興趣的朋友不妨來看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“Python進(jìn)程和線程知識(shí)點(diǎn)舉例分析”吧!

成都創(chuàng)新互聯(lián)是一家專注于網(wǎng)站設(shè)計(jì)制作、做網(wǎng)站與策劃設(shè)計(jì),索縣網(wǎng)站建設(shè)哪家好?成都創(chuàng)新互聯(lián)做網(wǎng)站,專注于網(wǎng)站建設(shè)10年,網(wǎng)設(shè)計(jì)領(lǐng)域的專業(yè)建站公司;建站業(yè)務(wù)涵蓋:索縣等地區(qū)。索縣做網(wǎng)站價(jià)格咨詢:18982081108

多線程

一個(gè)進(jìn)程至少包含一個(gè)線程,其實(shí)進(jìn)程就是由若干個(gè)線程組成的。線程是操作系統(tǒng)直接支持的執(zhí)行單元,因此高級(jí)語言通常都內(nèi)置多線程的支持,Python 也不例外,而且Python 的線程是真正的 Posix Thread ,而不是模擬出來的線程。

多線程的運(yùn)行有如下優(yōu)點(diǎn):

  • 使用線程可以把占據(jù)長(zhǎng)時(shí)間的程序中的任務(wù)放到后臺(tái)去處理。

  • 用戶界面可以更加吸引人,比如用戶點(diǎn)擊了一個(gè)按鈕去觸發(fā)某些事件的處理,可以彈出一個(gè)進(jìn)度條來顯示處理的進(jìn)度。

  • 程序的運(yùn)行速度可能加快。

  • 在一些等待的任務(wù)實(shí)現(xiàn)上如用戶輸入、文件讀寫和網(wǎng)絡(luò)收發(fā)數(shù)據(jù)等,線程就比較有用了。在這種情況下我們可以釋放一些珍貴的資源如內(nèi)存占用等等。

線程可以分為:

  • 內(nèi)核線程:由操作系統(tǒng)內(nèi)核創(chuàng)建和撤銷。

  • 用戶線程:不需要內(nèi)核支持而在用戶程序中實(shí)現(xiàn)的線程。

Python 的標(biāo)準(zhǔn)庫提供了兩個(gè)模塊:_thread 和 threading,前者是低級(jí)模塊,后者是高級(jí)模塊,對(duì) _thread 進(jìn)行了封裝。大多數(shù)情況只需要采用 threading模塊即可,并且也推薦采用這個(gè)模塊。

這里再次以下載文件作為例子,用多線程的方式來實(shí)現(xiàn)一遍:

from random import randint
from threading import Thread, current_thread
from time import time, sleep
def download(filename):
 print('thread %s is running...' % current_thread().name)
 print('開始下載%s...' % filename)
 time_to_download = randint(5, 10)
 sleep(time_to_download)
 print('%s下載完成! 耗費(fèi)了%d秒' % (filename, time_to_download))
def download_multi_threading():
 print('thread %s is running...' % current_thread().name)
 start = time()
 t1 = Thread(target=download, args=('Python.pdf',), name='subthread-1')
 t1.start()
 t2 = Thread(target=download, args=('nazha.mkv',), name='subthread-2')
 t2.start()
 t1.join()
 t2.join()
 end = time()
 print('總共耗費(fèi)了%.3f秒' % (end - start))
 print('thread %s is running...' % current_thread().name)
if __name__ == '__main__':
 download_multi_threading()

實(shí)現(xiàn)多線程的方式和多進(jìn)程類似,也是通過 Thread 類創(chuàng)建線程對(duì)象,target 參數(shù)表示傳入需要執(zhí)行的函數(shù),args 參數(shù)是表示傳給函數(shù)的參數(shù),然后 name 是給當(dāng)前線程進(jìn)行命名,默認(rèn)命名是如 Thread- 1、Thread-2 等等。

此外,任何進(jìn)程默認(rèn)會(huì)啟動(dòng)一個(gè)線程,我們將它稱為主線程,主線程又可以啟動(dòng)新的線程,在 threading 模塊中有一個(gè)函數(shù) current_thread() ,可以返回當(dāng)前線程的實(shí)例。主線程實(shí)例的名字叫 MainThread,子線程的名字是在創(chuàng)建的時(shí)候指定,也就是 name 參數(shù)。

運(yùn)行結(jié)果:

thread MainThread is running...
thread subthread-1 is running...
開始下載Python.pdf...
thread subthread-2 is running...
開始下載nazha.mkv...
nazha.mkv下載完成! 耗費(fèi)了5秒
Python.pdf下載完成! 耗費(fèi)了7秒
總共耗費(fèi)了7.001秒
thread MainThread is running...

Lock

多線程和多進(jìn)程最大的不同在于,多進(jìn)程中,同一個(gè)變量,各自有一份拷貝存在于每個(gè)進(jìn)程中,互不影響,而多線程中,所有變量都由所有線程共享,所以,任何一個(gè)變量都可以被任何一個(gè)線程修改,因此,線程之間共享數(shù)據(jù)最大的危險(xiǎn)在于多個(gè)線程同時(shí)改一個(gè)變量,把內(nèi)容給改亂了。

下面是一個(gè)例子,演示了多線程同時(shí)操作一個(gè)變量,如何把內(nèi)存給改亂了:

from threading import Thread
from time import time, sleep
# 假定這是你的銀行存款:
balance = 0
def change_it(n):
 # 先存后取,結(jié)果應(yīng)該為0:
 global balance
 balance = balance + n
 balance = balance - n
def run_thread(n):
 for i in range(100000):
 change_it(n)
def nolock_multi_thread():
 t1 = Thread(target=run_thread, args=(5,))
 t2 = Thread(target=run_thread, args=(8,))
 t1.start()
 t2.start()
 t1.join()
 t2.join()
 print(balance)
if __name__ == '__main__':
 nolock_multi_thread()

運(yùn)行結(jié)果:

-8

代碼中定義了一個(gè)共享變量 balance,然后啟動(dòng)兩個(gè)線程,先存后取,理論上結(jié)果應(yīng)該是 0 。但是,由于線程的調(diào)度是由操作系統(tǒng)決定的,當(dāng) t1、t2 交替執(zhí)行時(shí),只要循環(huán)次數(shù)足夠多,balance 的結(jié)果就不一定是0了。

原因就是下面這條語句:

balance = balance + n

這條語句的執(zhí)行分為兩步的:

  • 先計(jì)算 balance + n,保存結(jié)果到一個(gè)臨時(shí)變量

  • 將臨時(shí)變量的值賦給 balance

也就是可以看成:

x = balance+n
balance=x

正常運(yùn)行如下所示:

初始值 balance = 0
t1: x1 = balance + 5 # x1 = 0 + 5 = 5
t1: balance = x1 # balance = 5
t1: x1 = balance - 5 # x1 = 5 - 5 = 0
t1: balance = x1 # balance = 0
t2: x2 = balance + 8 # x2 = 0 + 8 = 8
t2: balance = x2 # balance = 8
t2: x2 = balance - 8 # x2 = 8 - 8 = 0
t2: balance = x2 # balance = 0
結(jié)果 balance = 0

但實(shí)際上兩個(gè)線程是交替運(yùn)行的,也就是:

初始值 balance = 0
t1: x1 = balance + 5 # x1 = 0 + 5 = 5
t2: x2 = balance + 8 # x2 = 0 + 8 = 8
t2: balance = x2 # balance = 8
t1: balance = x1 # balance = 5
t1: x1 = balance - 5 # x1 = 5 - 5 = 0
t1: balance = x1 # balance = 0
t2: x2 = balance - 8 # x2 = 0 - 8 = -8
t2: balance = x2 # balance = -8
結(jié)果 balance = -8

簡(jiǎn)單說,就是因?yàn)閷?duì) balance 的修改需要多條語句,而執(zhí)行這幾條語句的時(shí)候,線程可能中斷,導(dǎo)致多個(gè)線程把同個(gè)對(duì)象的內(nèi)容該亂了。

要保證計(jì)算正確,需要給 change_it() 添加一個(gè)鎖,添加鎖后,其他線程就必須等待當(dāng)前線程執(zhí)行完并釋放鎖,才可以執(zhí)行該函數(shù)。并且鎖是只有一個(gè),無論多少線程,同一時(shí)刻最多只有一個(gè)線程持有該鎖。通過 threading 模塊的 Lock 實(shí)現(xiàn)。

因此代碼修改為:

from threading import Thread, Lock
from time import time, sleep
# 假定這是你的銀行存款:
balance = 0
lock = Lock()
def change_it(n):
 # 先存后取,結(jié)果應(yīng)該為0:
 global balance
 balance = balance + n
 balance = balance - n
def run_thread_lock(n):
 for i in range(100000):
 # 先要獲取鎖:
 lock.acquire()
 try:
 # 放心地改吧:
 change_it(n)
 finally:
 # 改完了一定要釋放鎖:
 lock.release()
def nolock_multi_thread():
 t1 = Thread(target=run_thread_lock, args=(5,))
 t2 = Thread(target=run_thread_lock, args=(8,))
 t1.start()
 t2.start()
 t1.join()
 t2.join()
 print(balance)
if __name__ == '__main__':
 nolock_multi_thread()

但遺憾的是 Python 并不能完全發(fā)揮多線程的作用,這里可以通過寫一個(gè)死循環(huán),然后通過任務(wù)管理器查看進(jìn)程的 CPU 使用率。

正常來說,如果有兩個(gè)死循環(huán)線程,在多核CPU中,可以監(jiān)控到會(huì)占用200%的CPU,也就是占用兩個(gè)CPU核心。

要想把 N 核CPU的核心全部跑滿,就必須啟動(dòng) N 個(gè)死循環(huán)線程。

死循環(huán)代碼如下所示:

import threading, multiprocessing
def loop():
 x = 0
 while True:
 x = x ^ 1
for i in range(multiprocessing.cpu_count()):
 t = threading.Thread(target=loop)
 t.start()

在 4 核CPU上可以監(jiān)控到 CPU 占用率僅有102%,也就是僅使用了一核。

但是用其他編程語言,比如C、C++或 Java來改寫相同的死循環(huán),直接可以把全部核心跑滿,4核就跑到400%,8核就跑到800%,為什么Python不行呢?

因?yàn)?Python 的線程雖然是真正的線程,但解釋器執(zhí)行代碼時(shí),有一個(gè) GIL鎖:Global Interpreter Lock,任何Python線程執(zhí)行前,必須先獲得GIL鎖,然后,每執(zhí)行100條字節(jié)碼,解釋器就自動(dòng)釋放GIL鎖,讓別的線程有機(jī)會(huì)執(zhí)行。這個(gè) GIL 全局鎖實(shí)際上把所有線程的執(zhí)行代碼都給上了鎖,所以,多線程在Python中只能交替執(zhí)行,即使100個(gè)線程跑在100核CPU上,也只能用到1個(gè)核。

GIL是 Python 解釋器設(shè)計(jì)的歷史遺留問題,通常我們用的解釋器是官方實(shí)現(xiàn)的 CPython,要真正利用多核,除非重寫一個(gè)不帶GIL的解釋器。

盡管多線程不能完全利用多核,但對(duì)于程序的運(yùn)行效率提升還是很大的,如果想實(shí)現(xiàn)多核任務(wù),可以通過多進(jìn)程實(shí)現(xiàn)多核任務(wù)。多個(gè)Python進(jìn)程有各自獨(dú)立的GIL鎖,互不影響。

ThreadLocal

采用多線程的時(shí)候,一個(gè)線程采用自己的局部變量會(huì)比全局變量更好,原因前面也介紹了,如果不加鎖,多個(gè)線程可能會(huì)亂改某個(gè)全局變量的數(shù)值,而局部變量是只有每個(gè)線程自己可見,不會(huì)影響其他線程。

不過,局部變量的使用也有問題,就是函數(shù)調(diào)用時(shí)候,傳遞起來會(huì)比較麻煩,即如下所示:

def process_student(name):
 std = Student(name)
 # std是局部變量,但是每個(gè)函數(shù)都要用它,因此必須傳進(jìn)去:
 do_task_1(std)
 do_task_2(std)
def do_task_1(std):
 do_subtask_1(std)
 do_subtask_2(std)
def do_task_2(std):
 do_subtask_2(std)
 do_subtask_2(std)

局部變量需要一層層傳遞給每個(gè)函數(shù),比較麻煩,有沒有更好的辦法呢?

一個(gè)思路是用一個(gè)全局的 dict ,然后用每個(gè)線程作為 key ,代碼例子如下所示:

global_dict = {}
def std_thread(name):
 std = Student(name)
 # 把std放到全局變量global_dict中:
 global_dict[threading.current_thread()] = std
 do_task_1()
 do_task_2()
def do_task_1():
 # 不傳入std,而是根據(jù)當(dāng)前線程查找:
 std = global_dict[threading.current_thread()]
 ...
def do_task_2():
 # 任何函數(shù)都可以查找出當(dāng)前線程的std變量:
 std = global_dict[threading.current_thread()]

這種方式理論上是可行的,它可以避免局部變量在每層函數(shù)中傳遞,只是獲取局部變量的代碼不夠優(yōu)雅,在 threading 模塊中提供了 local 函數(shù),可以自動(dòng)完成這件事情,代碼如下所示:

import threading
# 創(chuàng)建全局ThreadLocal對(duì)象:
local_school = threading.local()
def process_student():
 # 獲取當(dāng)前線程關(guān)聯(lián)的student:
 std = local_school.student
 print('Hello, %s (in %s)' % (std, threading.current_thread().name))
def process_thread(name):
 # 綁定ThreadLocal的student:
 local_school.student = name
 process_student()
t1 = threading.Thread(target= process_thread, args=('Alice',), name='Thread-A')
t2 = threading.Thread(target= process_thread, args=('Bob',), name='Thread-B')
t1.start()
t2.start()
t1.join()
t2.join()

運(yùn)行結(jié)果:

Hello, Alice (in Thread-A)
Hello, Bob (in Thread-B)

在代碼中定義了一個(gè)全局變量 local_school ,它是一個(gè) ThreadLocal 對(duì)象,每個(gè)線程都可以對(duì)它讀寫 student 屬性,但又不會(huì)互相影響,也不需要管理鎖的問題,這是 ThreadLocal 內(nèi)部會(huì)處理。

ThreadLocal 最常用的是為每個(gè)線程綁定一個(gè)數(shù)據(jù)庫連接,HTTP 請(qǐng)求,用戶身份信息等,這樣一個(gè)線程的所有調(diào)用到的處理函數(shù)都可以非常方便地訪問這些資源。

進(jìn)程 vs 線程

我們已經(jīng)分別介紹了多進(jìn)程和多線程的實(shí)現(xiàn)方式,那么究竟應(yīng)該選擇哪種方法來實(shí)現(xiàn)并發(fā)編程呢,這兩者有什么優(yōu)缺點(diǎn)呢?

通常多任務(wù)的實(shí)現(xiàn),我們都是設(shè)計(jì) Master-Worker,Master 負(fù)責(zé)分配任務(wù),Worker 負(fù)責(zé)執(zhí)行任務(wù),因此多任務(wù)環(huán)境下,通常是一個(gè) Master 和多個(gè) Worker。

如果用多進(jìn)程實(shí)現(xiàn) Master-Worker,主進(jìn)程就是 Master,其他進(jìn)程就是 Worker。

如果用多線程實(shí)現(xiàn) Master-Worker,主線程就是 Master,其他線程就是 Worker。

對(duì)于多進(jìn)程,最大的優(yōu)點(diǎn)就是穩(wěn)定性高,因?yàn)橐粋€(gè)子進(jìn)程掛了,不會(huì)影響主進(jìn)程和其他子進(jìn)程。當(dāng)然主進(jìn)程掛了,所有進(jìn)程自然也就掛,但主進(jìn)程只是負(fù)責(zé)分配任務(wù),掛掉概率非常低。著名的 Apache 最早就是采用多進(jìn)程模式。

缺點(diǎn)有:

  • 創(chuàng)建進(jìn)程代價(jià)大,特別是在 windows 系統(tǒng),開銷巨大,而 Unix/ Linux 系統(tǒng)因?yàn)榭梢哉{(diào)用 fork() ,所以開銷還行;

  • 操作系統(tǒng)可以同時(shí)運(yùn)行的進(jìn)程數(shù)量有限,會(huì)受到內(nèi)存和 CPU 的限制。

對(duì)于多線程,通常會(huì)快過多進(jìn)程,但也不會(huì)快太多;缺點(diǎn)就是穩(wěn)定性不好,因?yàn)樗芯€程共享進(jìn)程的內(nèi)存,一個(gè)線程掛斷都可能直接造成整個(gè)進(jìn)程崩潰。比如在Windows上,如果一個(gè)線程執(zhí)行的代碼出了問題,你經(jīng)??梢钥吹竭@樣的提示:“該程序執(zhí)行了非法操作,即將關(guān)閉”,其實(shí)往往是某個(gè)線程出了問題,但是操作系統(tǒng)會(huì)強(qiáng)制結(jié)束整個(gè)進(jìn)程。

進(jìn)程/線程切換

是否采用多任務(wù)模式,第一點(diǎn)需要注意的就是,一旦任務(wù)數(shù)量過多,效率肯定上不去,這主要是切換進(jìn)程或者線程是有代價(jià)的。

操作系統(tǒng)在切換進(jìn)程或者線程時(shí)的流程是這樣的:

  • 先保存當(dāng)前執(zhí)行的現(xiàn)場(chǎng)環(huán)境(CPU寄存器狀態(tài)、內(nèi)存頁等)

  • 然后把新任務(wù)的執(zhí)行環(huán)境準(zhǔn)備好(恢復(fù)上次的寄存器狀態(tài),切換內(nèi)存頁等)

  • 開始執(zhí)行任務(wù)

這個(gè)切換過程雖然很快,但是也需要耗費(fèi)時(shí)間,如果任務(wù)數(shù)量有上千個(gè),操作系統(tǒng)可能就忙著切換任務(wù),而沒有時(shí)間執(zhí)行任務(wù),這種情況最常見的就是硬盤狂響,點(diǎn)窗口無反應(yīng),系統(tǒng)處于假死狀態(tài)。

計(jì)算密集型vsI/O密集型

采用多任務(wù)的第二個(gè)考慮就是任務(wù)的類型,可以將任務(wù)分為計(jì)算密集型和 I/O 密集型。

計(jì)算密集型任務(wù)的特點(diǎn)是要進(jìn)行大量的計(jì)算,消耗CPU資源,比如對(duì)視頻進(jìn)行編碼解碼或者格式轉(zhuǎn)換等等,這種任務(wù)全靠 CPU 的運(yùn)算能力,雖然也可以用多任務(wù)完成,但是任務(wù)越多,花在任務(wù)切換的時(shí)間就越多,CPU 執(zhí)行任務(wù)的效率就越低。計(jì)算密集型任務(wù)由于主要消耗CPU資源,這類任務(wù)用 Python這樣的腳本語言去執(zhí)行效率通常很低,最能勝任這類任務(wù)的是C語言,我們之前提到了 Python 中有嵌入 C/C++ 代碼的機(jī)制。不過,如果必須用 Python 來處理,那最佳的就是采用多進(jìn)程,而且任務(wù)數(shù)量最好是等同于 CPU 的核心數(shù)。

除了計(jì)算密集型任務(wù),其他的涉及到網(wǎng)絡(luò)、存儲(chǔ)介質(zhì) I/O 的任務(wù)都可以視為 I/O 密集型任務(wù),這類任務(wù)的特點(diǎn)是 CPU 消耗很少,任務(wù)的大部分時(shí)間都在等待 I/O 操作完成(因?yàn)?I/O 的速度遠(yuǎn)遠(yuǎn)低于 CPU 和內(nèi)存的速度)。對(duì)于 I/O 密集型任務(wù),如果啟動(dòng)多任務(wù),就可以減少 I/O 等待時(shí)間從而讓 CPU 高效率的運(yùn)轉(zhuǎn)。一般會(huì)采用多線程來處理 I/O 密集型任務(wù)。

異步 I/O

現(xiàn)代操作系統(tǒng)對(duì) I/O 操作的改進(jìn)中最為重要的就是支持異步 I/O。如果充分利用操作系統(tǒng)提供的異步 I/O 支持,就可以用單進(jìn)程單線程模型來執(zhí)行多任務(wù),這種全新的模型稱為事件驅(qū)動(dòng)模型。Nginx 就是支持異步 I/O的 Web 服務(wù)器,它在單核 CPU 上采用單進(jìn)程模型就可以高效地支持多任務(wù)。在多核 CPU 上,可以運(yùn)行多個(gè)進(jìn)程(數(shù)量與CPU核心數(shù)相同),充分利用多核 CPU。用 Node.js 開發(fā)的服務(wù)器端程序也使用了這種工作模式,這也是當(dāng)下實(shí)現(xiàn)多任務(wù)編程的一種趨勢(shì)。

在 Python 中,單線程+異步 I/O 的編程模型稱為協(xié)程,有了協(xié)程的支持,就可以基于事件驅(qū)動(dòng)編寫高效的多任務(wù)程序。協(xié)程最大的優(yōu)勢(shì)就是極高的執(zhí)行效率,因?yàn)樽映绦蚯袚Q不是線程切換,而是由程序自身控制,因此,沒有線程切換的開銷。協(xié)程的第二個(gè)優(yōu)勢(shì)就是不需要多線程的鎖機(jī)制,因?yàn)橹挥幸粋€(gè)線程,也不存在同時(shí)寫變量沖突,在協(xié)程中控制共享資源不用加鎖,只需要判斷狀態(tài)就好了,所以執(zhí)行效率比多線程高很多。如果想要充分利用CPU的多核特性,最簡(jiǎn)單的方法是多進(jìn)程+協(xié)程,既充分利用多核,又充分發(fā)揮協(xié)程的高效率,可獲得極高的性能。

到此,相信大家對(duì)“Python進(jìn)程和線程知識(shí)點(diǎn)舉例分析”有了更深的了解,不妨來實(shí)際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

文章名稱:Python進(jìn)程和線程知識(shí)點(diǎn)舉例分析
文章源于:http://chinadenli.net/article34/jgjdpe.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供ChatGPT網(wǎng)站排名、營(yíng)銷型網(wǎng)站建設(shè)商城網(wǎng)站、關(guān)鍵詞優(yōu)化、軟件開發(fā)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

營(yíng)銷型網(wǎng)站建設(shè)
91免费一区二区三区| 91久久国产福利自产拍| 大香蕉再在线大香蕉再在线| 精品视频一区二区三区不卡| 成人午夜免费观看视频| 国产精品视频一区二区秋霞| 日韩国产精品激情一区 | 成人亚洲国产精品一区不卡| 久久经典一区二区三区| 手机在线观看亚洲中文字幕| 久久亚洲成熟女人毛片| 欧美成人黄色一区二区三区| 蜜桃臀欧美日韩国产精品| 国产亚州欧美一区二区| 国产精品99一区二区三区| 日韩人妻中文字幕精品| 狠狠做五月深爱婷婷综合| 欧美大胆女人的大胆人体| 日本高清加勒比免费在线| 日韩欧美中文字幕人妻| 婷婷九月在线中文字幕| 人妻一区二区三区多毛女| 福利视频一区二区在线| 国产精品99一区二区三区| 日韩在线中文字幕不卡| 国产综合香蕉五月婷在线| 日韩人妻有码一区二区| 好吊视频有精品永久免费| 亚洲中文字幕熟女丝袜久久| 日本三区不卡高清更新二区| 少妇一区二区三区精品| 国产毛片av一区二区三区小说| 精品国产品国语在线不卡| 我的性感妹妹在线观看| 成年午夜在线免费视频| 国产三级欧美三级日韩三级| 日本欧美一区二区三区就| 中国美女偷拍福利视频| 欧美乱视频一区二区三区| 不卡中文字幕在线视频| 最近中文字幕高清中文字幕无 |