3atv精品不卡视频,97人人超碰国产精品最新,中文字幕av一区二区三区人妻少妇,久久久精品波多野结衣,日韩一区二区三区精品

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

多线程编程指南

發布時間:2023/12/18 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 多线程编程指南 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
1.?

多線程編程指南1--線程基礎

線程編程指南1--線程基礎

多線程

本文出自:BBS水木清華站 作者:Mccartney (coolcat) (2002-01-29 20:25:25)

multithreading可以被翻譯成多線程控制。與傳統的UNIX不同,一個傳統 的UNIX進程包含一個單線程,而多線程(MT)則把一個進程分成很多可執行線 程,每一個線程都獨立運行。
閱讀本章可以讓你理解:
Defining Multithreading Terms
Benefiting From Multithreading
Looking At Multithreading Structure
Meeting Multithreading Standards

因為多線程可以獨立運行,用多線程編程可以
1) 提高應用程序響應;
2) 使多CPU系統更加有效;
3) 改善程序結構;
4) 占用更少的系統資源;
5) 改善性能;

1.1定義多線程術語:

線程:在進程的內部執行的指令序列;
單線程:單線程;
多線程:多線程;
用戶級線程:在用戶空間內的由線程函數庫進程控制的現成;
輕進程:又稱LWP,內核內部的執行核代碼和系統調用的線程;
綁定(bound)線程:永遠限制在LWP內的線程;
非綁定(unbound)線程:在LWP動態捆綁和卸綁的線程;
記數信號量:一個基于內存的同步機制;

1.1.1定義同時(concurrency)和并行(parallism):
在進程內至少同時有兩個線程進行(process)時存在同時性問題;至少同時有兩個線程在執行時存在并行問題;
在單處理器上執行的多線程的進程內部,處理器可以在線程中間切換執行, 這樣實現了同時執行;在共享內存多處理器上執行的同一個多線程進程,每一 個線程可以分別在不同的處理器上進行,是為并行。
當進程里的線程數不多于處理器的數量時,線程支持系統和操作系統保 證線程在不同的處理器上執行。例如在一個m處理器和m線程運行一個矩陣乘法, 每一個線程計算一列。

1.2多線程的益處

1.2.1提高應用程序響應
任何一個包含很多互不關聯的操作(activity)的程序都可以被重新設計, 使得每一個操作成為一個線程。例如,在一個GUI(圖形用戶界面)內執行一 個操作的同時啟動另外一個,就可以用多線程改善性能。

1.2.2使多處理器效率更高
典型情況下,有同時性需求的多線程應用程序不需要考慮處理器的數量。應用程序的性能在被多處理器改善的同時對用戶是透明的。
數學計算和有高度并發性需求的應用程序,比如矩陣乘法,在多處理器平臺上可以用多線程來提高速度。

1.2.3改善程序結構
許多應用程序可以從一個單一的、巨大的線程改造成一些獨立或半獨立的 執行部分,從而得到更有效的運行。多線程程序比單線程程序更能適應用戶需 求的變更。

1.2.4占用較少的系統資源
應用程序可以通過使用兩個或更多的進程共享內存的辦法來實現多于一個 現成的控制。然而,每一個進程都要有一個完整的地址空間和操作系統狀態表 項。用于創建和維護多進程大量的狀態表的開銷與多線程方法相比,在時間上 和空間上都更為昂貴。而且,進程所固有的獨立性使得程序員花費很多精力來 實現進程間的通信和同步。

1.2.5把線程和RPC結合起來
把多線程和RPC(remote procedure call,遠程過程調用)結合起來,你可以使用沒內存共享的多處理器(比方說一個工作站組)。這種結構把這組工作站當作一個大的多處理器系統,使應用程序分布得更加容易。
例如,一個線程可以創建子線程,每一個子進程可以做RPC,調用另外一 臺機器上的過程。盡管最早的線程僅僅創建一些并行的線程,這種并行可以包 括多臺機器的運行。
1.2.6提高性能
本部分的性能數據是從SPARC station2(Sun 4/75)上采集的。測量精度為微秒。
1. 線程創建時間
表1-1顯示了使用thread package做緩存的缺省堆棧來創建線程的時 間。時間的測量僅僅包括實際的生成時間。不包括切換到線程的時間。比 率(ratio)列給出了該行生成時間與前一行的比。 數據表明,線程是更加經濟的。創建一個新進程大概是創建一個 unbound線程的30倍,是創建一個包含線程和LWP的bound線程的5倍。
Table 1-1 Thread Creation Times
Operation Microseconds Ritio
Create unbound thread 52 -
Create bound thread 350 6.7
Fork() 1700 32.7
2. 線程同步(synchronization)時間
表1-2列出了兩個線程使用pv操作的同步時間。
Table 1-2 Thread Synchronization Times
Operation Microseconds Ratio
Unbound thread 66 -
Bound thread 390 5.9
Between Processes 200 3

1.3多線程結構一覽
傳統的UNIX支持現成概念--每一個進程包含一個單線程,所以用多進程就 是使用多線程。但是一個進程還有一個地址空間,創建一個新進程意味著需要 創建一個新的地址空間。
因此,創建一個進程是昂貴的,而在一個已經存在的進程內部創建線程是 廉價的。創建一個線程的時間比創建一個進程的時間要少成千倍,部分是因為 在線程間切換不涉及地址空間的切換。
在進程內部的線程間通信很簡單,因為線程們共享所有的東西--特別是地址空間。所以被一個線程生成的數據可以立刻提供給其他線程。
支持多線程的接口(界面)是通過一個函數庫libthread實現的。多線程通過把內核級資源和用戶級資源獨立開來提供了更多的靈活性。

1.3.1用戶級線程
線程僅僅在進程內部是可見的,在進程內部它們共享諸如地址空間、已經 打開的文件等所有資源。以下的狀態是線程私有的,即每一個線程的下列狀態 在進程內部是唯一的。
.線程號(Thread ID)
.寄存器狀態(包括程序計數器和堆棧指針)
.堆棧
.信號掩碼(Signal mask)
.優先級(Priority)
.線程私有的存儲段(Thread-private storage)
因為線程共享進程的執行代碼和大部分數據,共享數據被一個線程修改之 后可以進程內的其他線程見到。當一個進程內部線程與其他線程通信的時候, 可以不經過操作系統。
線程是多線程編程的主要主要借口。用戶級的線程可以在用戶空間操作, 從而避免了與內核之間的互相切換。一個應用程序可以擁有幾千個線程而不占 用太多的內核資源。占用內核資源的多少主要決定于應用程序本身。
在缺省情況下,線程是非常輕便的。但是,為了控制一個線程(例如,更 多地控制進程調度策略),應用程序應當綁定線程。當一個應用程序把線程的所 有執行資源綁定后,線程就變成了內核資源(參見第9頁"bound 線程")。 總之,solaris用戶級線程是:
.創建的低開銷,因為只在運行是占用用戶地址空間的虛擬內存的幾個bit。
.快速同步,因為同步是在用戶級進行,不需要接觸到內核級。
.可以通過線程庫libthread很容易地實現。
圖1-1 多線程系統結構(略)

1.3.2輕進程(Lightweight Porcesses:LWP)

線程庫采用內核支持的稱為輕進程的底層控制線程。你可以把LWP看作一個 可以執行代碼和系統調用的虛擬的CPU。
大多數程序員使用線程是并不意識到LWP的存在。下面的內容僅僅幫助理解 bound和unbound線程之間的區別。
------------------------------------
NOTE:Solaris2.x的LWP不同于SunOs4.0的LWP庫,后者在solaris2.x中不再被支持。
------------------------------------
類似于在stdio中fopen和fread調用open和read,線程接口調用LWP接口, 原因是一樣的。
LWP建立了從用戶級到內核級的橋梁。每個進程包含了一個或更多LWP,每個 LWP運行著一個或多個用戶線程。創建一個現成通常只是建立一個用戶環境 (context),而不是創建一個LWP。
在程序員和操作系統的精心設計下,用戶級線程庫保證了可用的LWP足夠驅動 當前活動的用戶級線程。但是,用戶線程和LWP之間不是一一對應的關系,用戶級 線程可以在LWP之間自由切換。
程序員告訴線程庫有多少線程可以同時"運行"。例如,如果程序員指定最多有 三個線程可以同時運行,至少要有3個可用的LWP。如果有三個可用的處理器,線程 將并行進行。如果這里只有一個處理器,操作系統將在一個處理器上運行三個LWP。 如果所有的LWP阻塞,線程庫將在緩沖池內增加一個LWP。
當一個用戶線程由于同步原因而阻塞,它的LWP將移交給下一個可運行的線程。 這種移交是通過過程間的連接(coroutine linkage),而不是做系統調用而完成。
操作系統決定哪一個LWP什么時候在哪一個處理器上運行。它不考慮進程中線 程的類型和數量。內核按照LWP的類型和優先級來分配CPU資源。線程庫按照相同 的方法來為線程分配LWP。每個LWP被內核獨立地分發,執行獨立的系統調用,引 起獨立的頁錯誤,而且在多處理器的情況下將并行執行。
一些特殊類型的LWP可以不被直接交給線程。(!?不明)

1.3.3非綁定線程Unbound Threads

在LWP緩沖池中排隊的線程稱為unbound thread。通常情況下我們的線程都是 unbound的,這樣他們可以在LWP之間自由切換。
線程庫在需要的時候激活LWP并把它們交給可以執行的線程。LWP管理線程的 狀態,執行線程的指令。如果線程在同步機制中被阻塞,或者其他線程需要運行, 線程狀態被存在進程內存中,LWP被移交給其他線程。
1.3.4綁定線程Bound Threads

如果需要,你可以將一個線程綁定在某個LWP上。
例如,你可以通過綁定一個線程來實現:
1. 將線程全局調度(例如實時)
2. 使線程擁有可變的信號棧
3. 給線程分配獨立的定時器和信號(alarm)
在線程數多于LWP時,bounded比unbound線程體現出一些優越性。
例如,一個并行的矩陣計算程序在每個線程當中計算每一行。如果每個處理器 都有一個LWP,但每個LWP都要處理多線程,每個處理器將要花費相當的時間來切換 線程。在這種情況下,最好使每個LWP處理一個線程,減少線程數,從而減少線程 切換。
在一些應用程序中,混合使用bound和unbound線程更加合適。
例如,有一個實時的應用程序,希望某些線程擁有全局性的優先級,并被實時 調度,其他線程則轉入后臺計算。另一個例子是窗口系統,大多數操作都是 unbound的,但鼠標操作需要占用一個高優先級的,bound的,實時的線程。

1.4多線程的標準

多線程編程的歷史可以回溯到二十世紀60年代。在UNIX操作系統中的發展是從 80年代中期開始的。也許是令人吃驚的,關于支持多線程有很好的協議,但是今 天我們仍然可以看到不同的多線程開發包,他們擁有不同的接口。
但是,某幾年里一個叫做POSIX1003.4a的小組研究多線程編程標準。當標準完 成后,大多數支持多線程的系統都支持POSIX接口。很好的改善了多線程編程的可 移植性。
solaris多線程支持和POSIX1003.4a沒有什么根本性的區別。雖然接口是不同 的,但每個系統都可以容易地實現另外一個系統可以實現的任何功能。它們之間沒 有兼容性問題,至少solaris支持兩種接口。即使是在同一個應用程序里,你也可 以混合使用它們。
用solaris線程的另一個原因是使用支持它的工具包,例如多線程調試工具 (multighreaded debugger)和truss(可以跟蹤一個程序的系統調用和信號), 可以很好地報告線程的狀態。



2.?

多線程編程指南2--用多線程編程

多線程

本文出自:BBS水木清華站 作者:Mccartney (coolcat) (2002-01-29 20:26:32)

2 用多線程編程

2.1線程(函數)庫(The Threads Library)

用戶級多線程是通過線程庫,libthread來實現的(參考手冊第3頁: library routines)。線程庫支持信號,為可運行的程序排隊,并負責同 時操縱多任務。
這一章討論libthread中的一些通用過程,首先接觸基本操作,然后循 序漸進地進入更復雜的內容。
創建線程-基本特性 Thr_create(3T)
獲得線程號 Thr_self(3T)
執行線程 Thr_yield(3T,the below is same)
掛起或繼續線程 Thr_suspend
Thr_continue
向線程送信號 Thr_kill
設置線程的調用掩模 Thr_sigsetmask
終止線程 Thr-exit
等待線程終止 Thr-join
維護線程的私有數據 Thr_keycreate
Thr_setspecific
Thr_getspecific
創建線程-高級特性 Thr_create
獲得最小堆棧容量 Thr_min_stack
獲得或設置線程的同時性等級 Thr_getconcurrency
Thr_setconcurrency
獲得或設置線程的優先級 Thr_getprio
Thr_setprio

2.1.1創建線程-基本篇

thr_create過程是線程庫所有過程當中最復雜的一個。這部分的內容僅適用于你使用thr_create的缺省參數來創建進程。
對于thr_create更加復雜的使用,包括如何使用自定參數,我們將在高級特性部分給出說明。
thr_create(3T)
這個函數用于在當前進程中添加一個線程。注意,新的線程不繼承未處理的信號,但繼承優先級和信號掩模。
#include
int thr_create(void *stack_base,size_t stack_size,
void *(*start_routine) (void*),void *arg,long flags,
thread_t *new_thread);
size_t thr_min_stack(void);
stack_base--新線程的堆棧地址。如果stack_base是空則thr_create()按 照stack_size為新線程分配一個堆棧。
Stack_size--新線程堆棧的字節數。如果本項為0,將使用缺省值,一般 情況下最好將此項設為0。并不是每個線程都需要指定堆棧空間。線程庫為每個線程的堆棧分配1M 的虛擬內存,不保留交換空間。(線程庫用mmap(2)的MAP_NORESERVE的選項 來實現這種分配)。
Start_routine--指定線程開始執行的函數。如果start_routine返回, 線程將用該函數的返回值作為退出狀態而退出。(參考thr_exit(3T))。
Flags--指定新線程的屬性,一般設置為0。
Flags的值是通過下列內容的位同或來實現的(最后四個flags在高級特性中給出)。
1. THR_DETACHED 將新線程分離,使得它的線程號和其他資源在線程 結束時即可以回收利用。當你不想等待線程終止時,將其置位。如果沒有明確的 同步需求阻礙,一個不掛起的,分離的線程可以在創建者的thr_create返回之前 終止并將其線程號分配給一個心得線程。
2. THR_SUSPENDED掛起新線程,直到被thr_continue喚醒。
3. THR_BOUND把新線程永久綁定在一個LWP上(生成一個綁定線程)。
4. THR_NEW_LWP將非綁定線程的同時性級別加1。
5. THR_DAEMON新線程為一個守護線程。
New_thread--指向存儲新線程ID的地址。多數情況下設置為0。
Return Values--thr_create()在成功執行后返回0并退出。任何其他返回值表明有錯誤發生。當以下情況被檢測到時,thr_create()失敗并返回響應的值。
EAGAIN :超出了系統限制,例如創建了太多的LWP。
ENOMEM:可用內存不夠創建新線程。
EINVAL:stack_base不是NULL而且stack_size比thr_minstack()函數返回的最小堆棧要小。

2.1.2獲取線程號

thr_self(3T) 獲得自身的線程號。
#include
thread_t thr_self(void)
返回值--調用者的線程號。

2.1.3放棄執行

thr_yield(3T)
thr_yield停止執行當前線程,將執行權限讓給有相同或更高優先權的線程。
#include
void thr_yield(void);

2.1.4掛起或繼續執行線程

thr_suspend(3T) 掛起線程。
#include
int thr_suspend(thread_t target_thread);
thr_suspend()立即掛起由target_thread指定的線程。在thr_suspend成功返回后,掛起的線程不再執行。后繼的thr_suspend無效。
Return Values--執行成功后返回0。其他返回值意味著錯誤。以下情況發生時,thr_suspend()失敗并返回相關值。
ESRCH: 在當前進程中找不到target_thread。

Thr_continue(3T)
Thr_continue()恢復執行一個掛起的線程。一旦線程脫離掛起狀態,后繼的
thr_continue將無效。
#include
int thr_continue(thread_t target_thread);
一個掛起的線程不會被信號喚醒。信號被掛起知道線程被thr-continue恢復執行。
返回值--成功執行后返回0。其他值意味著錯誤。在以下情況發生時,函數失敗并返回相關值。
ESRCH:target_thread在當前進程中找不到。

2.1.5向線程發信號

thr_kill(3T)向線程發信號
#include
#include
int thr_kill(thread_t target_thread,int sig);
thr_kill向線程號為target_thread的線程發送信號sig。Target_thread一定要與調用線程處于同一個進程內。參數sig一定是signal(5)中定義過的。
當sig是0時,錯誤檢查將被執行,沒有實際的信號被發送。這可以用來檢測arget_thread參數是否合法。
返回值--成功執行后返回0,其他值意味著錯誤。在以下情況發生時,函數失敗并返回相關值。
EINVAL:sig非法;
ESRCH:target_thread找不到;

2.1.6設置本線程的信號掩模

thr_sigsetmask(3T) 獲取或改變本線程的信號掩模(signal mask)
#include
#include
int thr_sigsetmask(int how,const sigset_t *set,sigset_t *oset);
how參數決定信號設置將被如何改變,可以是下列值之一:
SIG_BLOCK--在當前信號掩模上增加set,set指要阻塞的信號組。
SIG_UNBLOCK--在當前信號掩模上去掉set,set指要解除阻塞的信號組。
SIG_SETMASK--用新的掩模代替現有掩模,set指新的信號掩模。
當set的值是NULL時,how的值并不重要,信號掩模將不被改變。所以,要查詢當前的信號掩模,就給set賦值為NULL。
當參數oset不是NULL時,它指向以前的信號掩模存放的地方。
Return Values--正常執行后返回0。其他值意味著錯誤。在以下情況發生時, 函數失敗并返回相關值。
EINVAL:set不是NULL且how沒有被定義;
EFAULT:set或oset不是合法地址;

2.1.7終止線程

thr_exit(3T)
用來終止一個線程。
#include
void thr_exit(void *status);
thr_exit 函數終止當前線程。所有的私有數據被釋放。如果調用線程不是一個分離線程,線程的ID和返回狀態保留直到有另外的線程在等待。否則返回狀態被忽略,線程號被立刻重新使用。
返回值--當調用線程是進程中的最后一個非守護線程,進程將用狀態0退出。 當最初的線程從main()函數中返回時進程用該線程main函數的返回值退出。
線程可以通過兩種方式停止執行。第一種是從最初的過程中返回。第二種是 提供一個退出代碼,通過調用thr_exit()結束。下面的事情依賴于在線程創建時 flags的設置。
線程A終止的缺省操作(當flags的相應位設為0時,執行缺省操作)是保持 狀態,直到其它線程(不妨設為B)通過"聯合"的方式得知線程A已經死亡。聯合 的結果是B線程得到線程A的退出碼,A自動消亡。你可以通過位或來給flags的 THR_DETACHED參數置位,使得線程在thr_exit()之后或從最初過程返回后立即消 亡。在這種情況下,它的退出碼不會被任何線程獲得。
有一個重要的特殊情況,在主線程--即最初存在的線程--從主函數返回或調 用了exit(),整個進程將終止。所以在主線程中要注意不要過早地從主函數main 返回。
如果主線程僅僅調用了thr_exit(),僅僅是它自己死亡,進程不會結束,進 程內的其他線程將繼續運行(當然,如果所有的線程都結束,進程也就結束了)。
如果一個線程是非分離的,在它結束后一定要有其它進程與它"聯合",否則 該線程的資源就不會被回收而被新線程使用。所以如果你不希望一個線程被 "聯合",最好按照分離線程來創建。
另外一個flag參數是THR_DAEMON。使用這個標志創建的線程是守護線程,在 其他線程終止之后,這些線程自動終止。這些守護線程在線程庫內部特別有用。 守護線程可以用庫內函數創建--在程序的其他部分是不可見的。當程序中所 有的其他線程終止,這些線程自動終止。如果它們不是守護線程,在其它線程終 止后他們不會自動終止,進程不會自動結束。

2.1.8等待線程結束

thr_join(3T) 用thr_join函數來等待線程終止。
#include
int thr_join(thread_t wait_for,thread_t *departed,void **status);
thr_join()函數阻塞自身所在的線程,直到由wait_for指定的線程終止。指 定的線程一定與本線程在同一個進程內部,而且一定不是分離線程。當wait_for 參數為0時,thr_join等待任何一個非分離線程結束。換句話說,當不指定線程 號時,任何非分離線程的退出將導致thr_join()返回。
當departed參數不是NULL時,在thr_join正常返回時它指向存放終止線程ID 的地址。當status參數不是NULL時,在thr_join正常返回時它指向存放終止線程 退出碼的地址。
如果線程創建時指定了堆棧,在thr_join返回時堆棧可以被回收。由它返回 的線程號可以被重新分配。
不能有兩個線程同時等待同一個線程,如果出現這種情況,其中一個線程正 常返回,另外一個返回ESRCH錯誤。
返回值--thr_join()在正常執行后返回0,其他值意味著錯誤。在以下情況 發生時,函數失敗并返回相關值。
ESRCH wait_for不合法,等待的線程為分離現成。
EDEADLK 等待自身結束。
最后步驟
thr_join()有三個參數,提供了一定的靈活性。當你需要一個線程等待 直到另外一個指定的線程結束,應當把后者的ID提供為第一參數。如果 需要等待到任何其他的線程結束,將第一參數置零。
如果調用者想知道是那個線程終止,第二參數應當是儲存死線程的ID的地址。 如果不感興趣,將該參數置零。最后如果需要知道死線程的退出碼,應當指出接 收該錯誤碼的地址。
一個線程可以通過以下的代碼等待所有的非守護線程結束:
while(thr_join(0,0,0)==0)
第三個參數的聲明(void **)看上去很奇怪。相應的thr_exit()的參數為 void *。這樣做的意圖在于你的錯誤代碼為定長的四字節,c語言給定長4字節的 定義不能是void型,因為這以為著沒有參數。所以用void*。因為thr_join()的 第三參數必須是一個指向thr_exit()返回值的指針,所以類型必須是void **。
注意,thr_join()只在目標線程為非分離時有效。如果沒有特殊的同步要求 的話,線程一般都設置成分離的。
可以認為,分離線程是通常意義下的線程,而非分離線程知識特殊情況。

2.1.9簡單的例程

在例子2-1里,一個運行在頂部的線程,創建一個輔助線程來執行fetch過程, 這個輔助過程涉及到復雜的數據庫查詢,需要較長的時間。主線程在等待結果的 時候還有其他事情可做。所以它通過執行thr_join()來等待輔助過程結束。
操作結果被當作堆棧參數傳送,因為主線程等待spun-off線程結束。在一般 意義上,用malloc()存儲數據比通過線程的堆棧來存儲要好一些。????
Code Example 2-1 A Simple Threads Program
Void mainline(){

Char int result;
Thread_t helper;
Int status;

Thr_create(0,0,fetch,&result,0,&helper);
/* do something else for a while */
Thr_join(helper,0,&status);
/* it's now safe to use result*/
}
void fetch(int * result){
/*fetch value from a database */
*result=value;
thr_exit(0);
}

2.1.10維護線程專有數據

單線程C程序有兩種基本數據--本地數據和全局數據。多線程C程序增加了 一個特殊類型--線程專有數據(TSD)。非常類似與全局數據,只不過它是線程 私有的。
TSD是以線程為界限的。TSD是定義線程私有數據的唯一方法。每個線程專有 數據項都由一個進程內唯一的關鍵字(KEY)來標識。用這個關鍵字,線程可以 來存取線程私有的數據。
維護TSD的方法通過以下三個函數進行:
· thr_keycreate()--創建關鍵字
· thr_setspecific()--將一個線程綁定在一個關鍵字上
· thr_getspecific()--存儲指定地址的值

2.1.10.1 thr_keycreate(3T)
thr_keycreate()在進程內部分配一個標識TSD的關鍵字。關鍵字是進程內部唯一的,所有線程在創建時的關鍵字值是NULL。
一旦關鍵字被建立,每一個線程可以為關鍵字綁定一個值。這個值對于綁定的線程來說是唯一的,被每個線程獨立維護。
#include
int thr_keycreate(thread_key_t keyp,
void (*destructor)(void *value);
如果thr_keycreate()成功返回,分配的關鍵字被存儲在由keyp指向的區 域里。調用者一定要保證存儲和對關鍵字的訪問被正確地同步。
一個可選的析構函數,destructor,可以和每個關鍵字聯系起來。如果一 個關鍵字的destructor不空而且線程給該關鍵字一個非空值,在線程退出時該 析構函數被調用,使用當前的綁定值。對于所有關鍵字的析構函數執行的順序 是不能指定的。
返回值--thr_keycreate()在正常執行后返回0,其他值意味著錯誤。在以 下情況發生時,函數失敗并返回相關值。
EAGAIN 關鍵字的名字空間用盡
ENOMEM 內存不夠

2.1.10.2 Thr_setspecific(3T)

#include
int thr_setspecific(thread_key_t key,void *value);
thr_setspecific()為由key指定的TSD關鍵字綁定一個與本線程相關的值。 返回值--thr_setspecific在正常執行后返回0,其他值意味著錯誤。在以 下情況發生時,函數失敗并返回相關值。
ENOMEM 內存不夠
EINVAL 關鍵字非法

2.1.10.3 Thr_getspecific(3T)

#include
int thr_getspecific(thread_key_t key,void **valuep);
thr_getspecific()將與調用線程相關的關鍵字的值存入由valuep指定的區
域。
返回值--thr_getspecific()在正常執行后返回0,其他值意味著錯誤。在 以下情況發生時,函數失敗并返回相關值。
EINVAL 關鍵字非法。

2.1.10.5 全局和私有的線程專有數據

例程2-2是從一個多線程程序中摘錄出來的。這段代碼可以被任意數量的線 程執行,但一定要參考兩個全局變量:errno和mywindow,這兩個值是因線程而 異的,就是說是線程私有的。

Code Example 2-2 線程專有數據--全局且私有的
Body(){
……
while(srite(fd,buffer,size)==-1){
if(errno!=EINTR){
fprintf(mywindow,"%s/n",strerror(errno));
exit(1);
}
}
………
}
本線程的系統錯誤代碼errno可以通過線程的系統調用來獲得,而不是通過 其他線程。所以一個線程獲得的錯誤碼與其他線程是不同的。
變量mywindow指向一個線程私有的輸入輸出流。所以,一個線程的mywindow 和另外一個線程是不同的,因而最終體現在不同的窗口里。唯一的區別在于線程 庫來處理errno,而程序員需要精心設計mywindow。
下面一個例子說明了mywindow的設計方法。處理器把mywindow的指針轉換成為對_mywindow過程的調用。
然后調用thr_getspecific(),把全程變量mywindow_key和標識線程窗口的輸出參數win傳遞給它。

Code Example 2-3 將全局參考轉化為私有參考
#define mywindow _mywindow()
thread_key_t mywindow_key;
FILE * _mywindow(void){
FILE *win;
Thr_getspecific(mywindow_key,&win);
Return(win);
}
void thread_start(…){

make_mywindow();

}
變量mywindow標識了一類每個線程都有私有副本的變量;就是說,這些變量 是線程專有數據。每個線程調用make_mywindow()來初始化自己的窗口,并且生 成一個指向它的實例mywindow。 一旦過程被調用,現成可以安全地訪問mywindow,在_mywindow函數之后,線 程可以訪問它的私有窗口。所以,對mywindow的操作就象是直接操作線程私有 數據一樣。

Code Example 2-4 顯示了怎樣設置
Code Example 2-4 初始化TSD
Void make_mywindow(void){
FILE **win;
Static int once=0;
Static mutex_t lock;
Mutex_lock(&lock);
If (!once){
Once=1;
Thr_keycreate(&mywindow_key,free_key);
}
mutext_unlock(&lock);
win=malloc(sizeof(*win));
create_window(win,…);
thr_setspecific(mywindow_key,win);
}
void freekey(void *win){
free(win);
}
首先,給關鍵字mywindow_key賦一個唯一的值。這個關鍵字被用于標識 TSD。所以,第一個調用make_mywindow的線程調用thr_keycreate(),這個函 數給其第一個參數賦一個唯一的值。第二個參數是一個析構函數,用來在線程 終止后將TSD所占的空間回收。
下一步操作是給調用者分配一個TSD的實例空間。分配空間以后,調用 create_window過程,為線程建立一個窗口并用win來標識它。最后調用 thr_setspecific(),把win(即指向窗口的存儲區)的值與關鍵字綁在一起。
做完這一步,任何時候線程調用thr_getspecific(),傳送全局關鍵字, 它得到的都是該線程在調用thr_setspecific時與關鍵字綁定的值。 如果線程結束,在thr_keycreate()中建立的析構函數將被調用,每個析構 函數只有在終止的線程用thr_setspecific()為關鍵字賦值之后才會執行。
2.1.11創建線程--高級特性

2.1.11.1 thr_create(3T)

#include
int thr_create(void *stack_base,size_t stack_size,
void *(*start_routine)(void *),void * arg,
long flags,thread_t *newthread);
size_t thr_min_stack(void);
stack_base--新線程所用的堆棧地址。如果本參數為空,thr_create為新線程分配一個至少長stack_size的堆棧。
Stack_size--新線程使用堆棧的字節數。如果本參數為零,將使用缺省值。如果非零,一定要比調用thr_min_stack()獲得的值大。
一個最小堆棧也許不能容納start_routine需要的堆棧大小,所以如果 stack_size被指定,一定要保證它是最小需求與start_routine及它所調用的 函數需要的堆棧空間之和。
典型情況下,由thr_create()分配的線程堆棧從一個頁邊界開始,到離指 定大小最接近的頁邊界結束。在堆棧的頂部放置一個沒有訪問權限的頁,這樣, 大多數堆棧溢出錯誤發生在向越界的線程發送SIGSEGV信號的時候。由調用者分 配的線程堆棧 are used as is . ????
如果調用者使用一個預分配的堆棧,在指向該線程的thr_join()函數返回 之前,堆棧將不被釋放,即使線程已經終止。然后線程用該函數的返回值作為 退出碼退出。
通常情況下,你不需要為線程分配堆棧空間。線程庫為每個線程的堆棧分 配一兆的虛擬內存,不保留交換空間(線程庫用mmap(2)的MAP_NORESERVE選項 來進行分配)。
每個用線程庫創建的線程堆棧有一個"紅區"。線程庫將一個紅區放置在堆 棧頂部來檢測溢出。該頁是沒有訪問權限的,在訪問時將導致一個頁錯誤。紅 區被自動附加在堆棧頂端,不管是用指定的容量還是缺省的容量。
只有在你絕對確信你給的參數正確之后才可以指定堆棧。沒有多少情況需 要去指定堆棧或它的大小。即使是專家也很難知道指定的堆棧和容量是否正確。 這是因為遵循ABI的程序不能靜態地決定堆棧的大小。它的大小依賴于運行時的 環境。

2.1.11.2建立你自己的堆棧

如果你指定了線程堆棧的大小,要保證你考慮到了調用它的函數和它調用的函數需要的空間。需要把調用結果、本地變量和消息結構的成分都考慮進來。
偶爾你需要一個與缺省堆棧略有不同的堆棧。一個典型的情況是當線程需 要一兆以上的堆棧空間。一個不太典型的情況是缺省堆棧對于你來說太大了。 你可能會創建上千個線程,如果使用缺省堆棧時,就需要上G的空間。
堆棧的上限是很顯然的,但下限呢?一定要有足夠的堆棧空間來保存堆棧 框架和本地變量。
你可以用thr_min_stack()函數來獲得絕對的最小堆棧容量,它返回運行一 個空過程所需要的堆棧空間。有實際用途的線程需要的更多,所以在減小線程 堆棧的時候要小心。
你通過兩種方式指定一個堆棧。第一種是給堆棧地址賦空值,由實時的運 行庫來為堆棧分配空間,但需要給stack_size參數提供一個期望的值。
另外一種方式是全面了解堆棧管理,為thr_create函數提供一個堆棧的指 針。這意味著你不但要負責為堆棧分配空間,你還要考慮在線程結束后釋放這 些空間。
在你為自己的堆棧分配空間之后,一定要調用一個mprotect(2)函數來為它 附加一個紅區。
Start_routine--指定新線程首先要執行的過程。當start_routine返回時, 線程用該返回值作為退出碼退出(參考thr_exit(3T))。
注意,你只能指定一個參數。如果你想要多參數,把他們作成一個(例如 寫入一個結構)。這個參數可以是任何一個由void說明的數據,典型的是一個 4字節的值。任何更大的值都需要用指針來間接傳送。
Flags--指定創建線程的屬性。在多數情況下提供0即可。
Flags的值通過位或操作來賦。
THR_SUSPENDED--新線程掛起,在thr_continue()后再執行 start_routine。用這種辦法在運行線程之前對它進行操作(例如改變 優先級)。分離線程的終止被忽略。
THR_DETACHED--將新線程分離,使線程一旦終止,其資源可以得到立刻 回收利用。如果你不需要等待線程結束,設置此標志。 如果沒有明確的同步要求,一個不掛起的,分離的線程可以在它 的創建者調用的thr_create函數返回之前終止并將線程號和其他資源 移交給其他線程使用。
THR_BOUND--將一個新線程永久綁定在一個LWP上(新線程為綁定線程)。
THR_NEW_LWP--給非綁定線程的同時性等級加1。效果類似于用 thr_setconcurrency(3T)來增加同時性等級,但是使用 thr_setconcurrency()不影響等級設置。典型的,THR_NEW_LWP在LWP池 內增加一個LWP來運行非綁定線程。
如果你同時指定了THR_BOUND和THR_NEW_LWP,兩個LWP被創建,一 個被綁定在該線程上,另外一個來運行非綁定線程。
THR_DAEMON--標志新線程為守護線程。當所有的非守護線程退出后進程 結束。守護線程不影響進程退出狀態,在統計退出的線程數時被忽略。 一個進程可以通過調用exit(2)或者在所有非守護線程調用 thr_exit(3T)函數終止的時候終止。一個應用程序,或它調用的一個庫, 可以創建一個或多個在決定是否退出的時候被忽略的線程。用 THR_DAEMON標志創建的線程在進程退出的范疇不被考慮。 New_thread--在thr_create()成功返回后,保存指向存放新線程ID的地址。 調用者負責提供保存這個參數值指向的空間。 如果你對這個值不感興趣,給它賦值0。 返回值--thr_thread在正常執行后返回0,其他值意味著錯誤。在以下情況 發生時,函數失敗并返回相關值。
EAGAIN 超過系統限制,例如創建了太多的LWP。
ENOMEM 內存不夠創建新線程。
EINVAL stack_base非空,但stack_size比thr_minstack()的返回值小。

2.1.11.3 Thr_create(3T)例程

例2-5顯示了怎樣用一個與創建者(orig_mask)不同的新的信號掩模來創建新線程。
在這個例子當中,new_mask被設置為屏蔽SIGINT以外的任何信號。然后創建者的信號掩模被改變,以便新線程繼承一個不同的掩模,在thr_create()返回后,創建者的掩模被恢復為原來的樣子。
例子假設SIGINT不被創建者屏蔽。如果最初是屏蔽的,用相應的操作去掉屏蔽。另外一種辦法是用新線程的start routine來設置它自己的信號掩模。
Code Example 2-5 thr_create() Creates Thread With New Signal Mask
thread_t tid;
sigset_t new_mask, orig_mask;
int error;
(void)sigfillset(&new_mask);
(void)sigdelset(&new_mask, SIGINT);
(void)thr_sigsetmask(SIGSETMASK, &new_mask, &orig_mask):
error = thr_create(NULL, 0, dofunc, NULL, 0, &tid);
(void)thr_sigsetmask(SIGSETMASK, NULL, &orig_mask);

2.1.12獲得最小堆棧

thr_min_stack(3T) 用thr_min_stack(3T)來獲得線程的堆棧下限
#include
size_t thr_min_stack(void);
thr_min_stack()返回執行一個空線程所需要的堆棧大小(空線程是一個創 建出來執行一個空過程的線程)。
如果一個線程執行的不僅僅是空過程,應當給它分配比thr_min_stack()返 回值更多的空間。
如果線程創建時由用戶指定了堆棧,用戶應當為該線程保留足夠的空間。在 一個動態連接的環境里,確切知道線程所需要的最小堆棧是非常困難的。
大多數情況下,用戶不應當自己指定堆棧。用戶指定的堆棧僅僅用來支持那 些希望控制它們的執行環境的應用程序。
一般的,用戶應當讓線程庫來處理堆棧的分配。線程庫提供的缺省堆棧足夠 運行任何線程。

2.1.13設置線程的同時性等級

2.1.13.1 thr_getconcurrency(3T)

用thr_getconcurrency()來獲得期望的同時性等級的當前值。實際上同時活動的線程數可能會比這個數多或少。
#include
int thr_getconcurrency(void)
返回值--thr_getconcurrency()為期望的同時性等級返回當前值。

2.1.13.2 Thr_setconcurrency(3T)

用thr_setconcurrency()設置期望的同時性等級。
#include
int thr_setconcurrency(new_level)
進程中的非綁定線程可能需要同時活動。為了保留系統資源,線程系統的缺 省狀態保證有足夠的活動線程來運行一個進程,防止進程因為缺少同時性而死鎖。
因為這也許不會創建最有效的同時性等級,thr_setconcurrency()允許應用 程序用new_level給系統一些提示,來得到需要的同時性等級。
實際的同時活動的線程數可能比new_level多或少。
注意,如果沒有用thr_setconcurrency調整執行資源,有多個 compute-bound(????)線程的應用程序將不能分配所有的可運行線程。
你也可以通過在調用thr_create()時設置THR_NEW_LWP標志來獲得期望的同時性等級。
返回值--thr_setconcurrency()在正常執行后返回0,其他值意味著錯誤。在以下情況發生時,函數失敗并返回相關值。
EAGAIN 指定的同時性等級超出了系統資源的上限。
EINVAL new_level的值為負。

2.1.14得到或設定線程的優先級

一個非綁定線程在調度時,系統僅僅考慮進程內的其他線程的簡單的優先級, 不做調整,也不涉及內核。線程的系統優先級的形式是唯一的,在創建進程時繼 承而來。

2.1.14.1 Thr_getprio(3T)

用thr_getprio()來得到線程當前的優先級。
#include
int thr_getprio(thread_t target_thread,int *pri)
每個線程從它的創建者那里繼承優先級,thr_getprio把target_thread當前 的優先級保存到由pri指向的地址內。
返回值--thr_getprio()在正常執行后返回0,其他值意味著錯誤。在以下情 況發生時,函數失敗并返回相關值。
ESRCH target_thread在當前進程中不存在。

2.1.14.2 Thr_setprio(3T)

用thr_setprio()來改變線程的優先級。
#include
int thr_setprio(thread_t target_thread,int pri)

thr_setprio改變用target_thread指定的線程的優先級為pri。缺省狀態下, 線程的調度是按照固定的優先級--從0到最大的整數--來進行的,即使不全由優先 級決定,它也占有非常重要的地位。Target_thread將打斷低優先級的線程,而讓 位給高優先級的線程。
返回值--thr_setprio()在正常執行后返回0,其他值意味著錯誤。在以下情況發生時,函數失敗并返回相關值。
ESRCH target_thread在當前進程中找不到。
EINVAL pri的值對于和target_thread相關的調度等級來說沒有意義。

2.1.15線程調度和線程庫函數

下面的libthread函數影響線程調度

2.1.15.1 thr_setprio()和thr_getprio()
這兩個函數用來改變和檢索target_thread的優先級,這個優先級在用戶級線程庫調度線程時被引用,但與操作系統調度LWP的優先級無關。
這個優先級影響線程和LWP的結合--如果可運行的線程比LWP多的時候,高優 先級的線程得到LWP。線程的調度是"專橫"的,就是說,如果有一個高優先級的線 程得不到空閑的LWP,而一個低優先級的線程占有一個LWP,則低優先級的線程被 迫將LWP讓給高優先級的線程。

2.1.15.2 thr_suspend()和thr_continue()
這兩個函數控制線程是否被允許運行。調用thr_suspend(),可以把線程設置 為掛起狀態。就是說,該線程被擱置,即使有可用的LWP。在其他線程以該線程為 參數調用thr_continue后,線程退出掛起狀態。這兩個函數應當小心使用--它們 的結果也許是危險的。例如,被掛起的線程也許是處在互鎖狀態的,將它掛起可 能會導致死鎖。
一個線程可以在創建時用THR_SUSPENDED標志設置為掛起。

2.1.15.3 thr_yield()
Thr_yield函數使線程在相同優先級的線程退出掛起狀態后交出LWP。(不會有 更高優先級的線程可運行而沒有運行,因為它會通過強制的方式取得LWP)。這個 函數具有非常重要的意義,因為在LWP上沒有分時的概念(盡管操作系統在執行LWP 時有分時)。
最后,應當注意priocntl(2)也會影響線程調度。更詳細的內容請參照"LWP和調度等級"。

3.

多線程編程指南3--使用同步對象編程

多線程

本文出自:BBS水木清華站 作者:Mccartney (coolcat) (2002-01-29 20:28:07)

3 使用同步對象來編程

本章定義了四種可用的同步類型,并且討論實現同步的注意事項。
互斥鎖(mutex)
條件變量(condition variable)
多讀單寫鎖(multi-read,single-write lock)
信號量(semophore)
進程間同步(process synchronization)
同步原語的比較(compare primitive)

同步對象是內存中的變量,你可以象訪問一般的數據那樣來訪問它。不同進程內的線程可以通過共享內存中的同步變量來同步,即使這些線程互不可見。
同步變量可以放置在文件當中,可以比創建它的進程擁有更長的生命。
同步對象的類型包括:
· 互斥鎖
· 狀態變量
· 讀寫鎖
· 信號燈(信號量)
在下面幾種情況下,同步是重要的:
· 在兩個或更多個進程內的線程可以合用一個同步變量。注意,同步變量應當被一個進程初始化,在第二次初始化時,該同步變量被設置為解鎖狀態。
· 同步是唯一保證共享數據持久的辦法。
· 一個進程可以映射一個文件并通過一個線程將其加鎖,修改完成之后,該線程釋放文件鎖并恢復文件。在文件加鎖的過程中,任何程序中的任何 線程想要加鎖時都會阻塞,直至解鎖;
· 同步可以保證易變數據的安全。
· 同步對于簡單變量也是很重要的,例如整數。在整數沒有和總線對齊或
大于數據寬度的情況下,讀寫一個整數可能需要多個內存周期。雖然在SPARC系統上不會發生這樣的情況,但移植程序時不能不考慮這一點;

3.1互斥鎖

用互斥鎖可以使線程順序執行。互斥鎖通常只允許一個線程執行一個關鍵部分的代碼,來同步線程。互斥鎖也可以用來保護單線程代碼。
Table 3-1 互斥鎖函數
函數 操作
Mutex_init(3T) 初始化一個互斥鎖
Mutext_lock(3T) 給一個互斥鎖加鎖
Mutex_trylock(3T) 加鎖,如失敗不阻塞
Mutex_unlock(3T) 解鎖
Mutex_destroy(3T) 解除互斥狀態
如果兩個進程有共享且可寫的內存,且做了相應的初始化設置后(參見mmap(2)),互斥鎖可以實現進程間的線程同步。
互斥鎖在使用前一定要初始化。
多線程等待一個互斥鎖時,其獲得互斥鎖的順序是不確定的。

3.1.1初始化一個互斥鎖

mutex_init(3T)
#include ( or #include )
int mutex_init(mutex_t *mp, int type, void * arg);
用mutex_init()來初始化一個由mp指向的互斥鎖。Type可以是以下值之一(arg現在先不談)。
USYNC_PROCESS 互斥鎖用來同步進程間的線程。
USYNC_THREAD 互斥鎖只用來同步進程內部的線程。
互斥鎖也可以通過分配零內存來初始化,在此種情況下應當設定USYNC_THREAD。
一定不會有多個線程同時初始化同一個互斥鎖。一個互斥鎖在使用期間一定不會被重新初始化。
返回值--mutex_init()在成功執行后返回零。其他值意味著錯誤。在以下情況發生時,函數失敗并返回相關值。
EINVAL 非法參數
EFAULT mp或者arg指向一個非法地址。

3.1.2給互斥鎖加鎖

mutex_lock(3T)
#include (or #include )
int mutex_lock(mutex_t *mp);
用mutex_lock()鎖住mp指向的互斥鎖。如果mutex已經被鎖,當前調用線程阻塞直到互斥鎖被其他線程釋放(阻塞線程按照線程優先級等待)。當mutex_lock()返回,說明互斥鎖已經被當前線程成功加鎖。
返回值--mutex_lock()在成功執行后返回零。其他值意味著錯誤。在以下情況發生時,函數失敗并返回相關值。
EINVAL 非法參數
EFAULT mp指向一個非法地址。

3.1.3加非阻塞互斥鎖

mutex_trylock(3T)
#include (or #include )
int mutex_trylock(mutex_t *mp);
用mutex_trylock()來嘗試給mp指向的互斥鎖加鎖。這個函數是mutex_lock()的非阻塞版本。當一個互斥鎖已經被鎖,本調用返回錯誤。否則,互斥鎖被調用者加鎖。
返回值--mutex_trylock()在成功執行后返回零。其他值意味著錯誤。在以下情況發生時,函數失敗并返回相關值。
EINVAL 非法參數
EFAULT mp指向一個非法地址。
EBUSY mp指向的互斥鎖已經被鎖。

3.1.4給互斥鎖解鎖

mutex_unlock(3T)
#include (or #include )
int mutex_unlock(mutex_t *mp);
用mutex_unlock()給由mp指向的互斥鎖解鎖。互斥鎖必須處于加鎖狀態且調用本函數的線程必須是給互斥鎖加鎖的線程。如果有其他線程在等待互斥鎖,在等待隊列頭上的線程獲得互斥鎖并脫離阻塞狀態。
返回值--mutex_unlock()在成功執行后返回零。其他值意味著錯誤。在以下情況發生時,函數失敗并返回相關值。
EINVAL 非法參數
EFAULT mp指向一個非法地址。

3.1.5清除互斥鎖

mutex_destroy(3T)
#include (or #include )
int mutex_destroy(mutex_t *mp);
用mutex_destroy()函數解除由mp指向的互斥鎖的任何狀態。儲存互斥鎖的內存不被釋放。
返回值--mutex_destroy()在成功執行后返回零。其他值意味著錯誤。在以下情況發生時,函數失敗并返回相關值。
EINVAL 非法參數
EFAULT mp指向一個非法地址。

3.1.6互斥鎖代碼示例
Code Example 3-1 Mutex Lock Example
Mutex_t count_mutex;
Int count;

Increment_count()
{ mutex_lock(&count_mutex);
count=count+1;
mutex_unlock(&cout_mutex);
}
int get_count()
{ int c;
mutex_lock(&count_mutex);
c=count;
mutex_unlock(&count_mutex);
return(c);
}
在示例3-1中兩個函數用互斥鎖實現不同的功能,increment_count()保證對共享變量的一個原子操作(即該操作不可中斷),get_count()用互斥鎖保證讀取count期間其值不變。

*為鎖設置等級

你可能會需要同時訪問兩種資源。也許你在用其中一種資源時,發現需要另外一 種。就象我們在示例3-2中看到的,如果兩個線程希望占有兩種資源,但加互斥鎖的 順序不同,有可能會發生問題。在這個例子當中,兩個線程分別給互斥鎖1和2加鎖, 在它們想給另外的資源加鎖的時候,將會發生死鎖。
Code Example 3-2 Deadlock
Thread 1:

Mutex_lock(&m1)
/* use resource 1*/
mutex_lock(&m2);
/* use resources 1 and 2*/
mutex_unlock(&m2);
mutex_unlock(&m1);

Thread 2:

Mutex_lock(&m2);
/*use resource 2*/
mutex_lock(&m1);
/* use resources 1 and 2*/
mutex_unlock(&m1);
mutex_unlock(&m2);
避免這個問題的最好辦法是在線程給多個互斥鎖加鎖時,遵循相同的順序。這種技術的一種實現叫"鎖的等級":在邏輯上為每個鎖分配一個數進行排序。
如果你已經擁有一個等級為I的互斥鎖,你將不能給等級小于I的互斥鎖加鎖。
---------------------------------------
注意--lock_init可以檢測這個例子當中死鎖的類型。避免死鎖的最好辦法是采用等
級鎖:如果對互斥鎖的操作遵循一個預先定義的順序,死鎖將不會發生。
---------------------------------------
但是,這種技術并非總可以使用--有時你必須對互斥鎖進行不按照預定義順序的 操作。為了在這種情況下阻止死鎖,一個線程在發現死鎖用其他方法無法避免時, 必須釋放已經占有的所有資源。示例3-3顯示了這種方法。

Code Example 3-3 條件鎖
Thread 1:
Mutex_lock(&m1);
Mutex_lock(&m2);
Mutex_unlock(&m2);
Mutex_unlock(&m1);

Thread 2:
For(;{
Mutex_lock(&m2);
If(mutex_trylock(&m1)==0)
/*got it*/
break;
/*didn't get it */
mutex_unlock(&m1);
}
mutex_unlock(&m1);
mutex_unlock(&m2);
在上例中,線程1按照預定的順序加鎖,但線程2打亂了次序。為避免死鎖,線程2必須小心操作互斥鎖1:如果設置在等待互斥鎖釋放時阻塞,則可能導致死鎖。
為保證上述情況不會發生,線程2調用mutex_trylock,如果互斥鎖可用則用, 不可用則立刻返回失敗。在這個例子當中,線程2一定要釋放互斥鎖2,以便線程1 可以使用互斥鎖1和互斥鎖2。

3.1.7鎖內嵌于單鏈表當中

示例3-4同時占有3個鎖,通過鎖等級定義避免死鎖。
Code Example 3-4 單鏈表結構
Typedef struct node1{
Int value;
Struct node1 *link;
Mutex_t lock;
}node1_t;
node1_t Listhead;
此例利用單鏈表結構的每一個節點存儲一個互斥鎖。為了刪除一個互斥鎖,要從listhead開始搜索(它本身不會被刪除),知道找到指定的節點。
為了保證同時刪除不會發生,在訪問其內容之前要先鎖定節點。因為所有的搜索從listhead開始按順序進行,所以不會出現死鎖。
如果找到指定節點,對該節點和其前序節點加鎖,因為兩個節點都需要改變。因為前序節點總是首先加鎖,死鎖將不會發生。
下面C程序從單鏈表中刪除一項。
Code Example 3-5 內嵌鎖的單鏈表
Node1_t * delete(int value){
Node1_t * prev, *current;
Prev =&listhead;
Mutex_lock(&prev->lock);
While((current=prev->link)!=NULL){
Mutex_lock(¤t->lock);
If(current->value==value){
Prev->link=current->link;
Mutex_unlock(¤t->lock);
Mutex_unlock(&prev->lock);
Current->link=NULL;
Return(current);
}
mutex_unlock(&prev->lock);
prev=current;
}
mutex_unlock(&prev->lock);
return(NULL);
}

3.1.8內嵌在環狀鏈表中的鎖

示例3-6把前例的單鏈表改為環鏈表。環鏈表沒有顯式的表頭;一個線程可以和某個節點連接,對該節點及其鄰節點進行操作。等級鎖在這里不容易使用,因為其鏈表是環狀的。
Code Example 3-6 Circular Linked List Structure
Typedef struct node 2 {
Int value;
Struct node2 *link;
Mutex_t lock;
} node2_t;

下面的C程序給兩個節點加鎖,并對它們做操作。
Code Example 3-7 內嵌鎖的環鏈表
Void Hit Neighbor(node2_t *me){
While(1){
Mutex_lock(&me->lock);
If(mutex_lock(&me->link->lock)){
/* failed to get lock*/
mutex_unlock(&me->lock);
continue;
}
break;
}
me->link->value += me->value;
me->value /=2;
mutex_unlock(&me->link->lock);
mutex_unlock(&me->lock);
}

3.2條件變量

用條件變量來自動阻塞一個線程,直到某特殊情況發生。通常條件變量和互斥鎖同時使用。
Table3-2 有關條件變量的函數
函數 操作
Cond_init(3T) 初始化條件變量
Cond_wait(3T) 基于條件變量阻塞
Cond_signal(3T) 解除指定線程的阻塞
Cond_timedwait(3T) 阻塞直到指定事件發生
Cond_broadcast(3T) 解除所有線程的阻塞
Cond_destroy(3T) 破壞條件變量
通過條件變量,一個線程可以自動阻塞,直到一個特定條件發生。條件的檢測是在互斥鎖的保護下進行的。
如果一個條件為假,一個線程自動阻塞,并釋放等待狀態改變的互斥鎖。如 果另一個線程改變了條件,它發信號給關聯的條件變量,喚醒一個或多個等待它 的線程,重新獲得互斥鎖,重新評價條件。
如果兩進程共享可讀寫的內存,條件變量可以被用來實現這兩進程間的線程同步。
使用條件變量之前要先進行初始化。而且,在有多個線程等待條件變量時,它們解除阻塞不存在確定的順序。

3.2.1初始化條件變量

cond_init(3T)
#include (or #include )
int cond_init(cond_t *cvp, int type, int arg);
用cond_init()初始化有cvp指向的條件變量。Type可以是如下值之一(arg先
不談):
USYNC_PROCESS 條件變量可以在進程間實現線程同步;
USYNC_THREAD 條件變量只能在進程內部對線程同步;
條件變量可以用分配零內存來初始化,在這種情況下一定要是USYNC_THREAD。
多線程不能同時初始化同一個條件變量。如果一個條件變量正在使用,它不能被重新初始化。
返回值--cond_init()在成功執行后返回零。其他值意味著錯誤。在以下情況發生時,函數失敗并返回相關值。
EINVAL 非法參數
EFAULT mp指向一個非法地址。

3.2.2關于條件變量阻塞

cond_wait(3T)
#include (or #include )
int cond_wait(cond_t *cvp, mutex_t *mp);
用cond_wait()釋放由mp 指向的互斥鎖,并且使調用線程關于cvp指向的條件 變量阻塞。被阻塞的線程可以被cond_signal(), cond_broadcast(),或者由fork() 和傳遞信號引起的中斷喚醒。
與條件變量關聯的條件值的改變不能從cond_wait()的返回值得出,這樣的狀 態必須被重新估價。
即使是返回錯誤信息,Cond_wait()通常在互斥鎖被調用線程加鎖后返回。
函數阻塞直到條件被信號喚醒。它在阻塞前自動釋放互斥鎖,在返回前在自動 獲得它。
在一個典型的應用當中,一個條件表達式在互斥鎖的保護下求值。如果條件表 達式為假,線程基于條件變量阻塞。當一個線程改變條件變量的值時,條件變量獲 得一個信號。這使得等待該條件變量的一個或多個線程退出阻塞狀態,并試圖得到 互斥鎖。
因為在被喚醒的線程的cond_wait()函數返回之前條件已經改變,導致等待的 條件在得到互斥鎖之前必須重新測試。推薦的辦法是在while循環中寫條件檢查。

Mutex_lock();
While(condition_is_false)
Cond_wait();
Mutes_unlock();
如果有多個線程關于條件變量阻塞,其退出阻塞狀態的順序不確定。
返回值--cond_wait()在成功執行后返回零。其他值意味著錯誤。在以下情況發生時,函數失敗并返回相關值。
EFAULT cvp指向一個非法地址。
EINTR 等待被信號或fork()中斷。

3.2.3使指定線程退出阻塞狀態

cond_signal(3T)
#include (or #include )
int cond_signal (cond_t *cvp);
用cond_signal()使得關于由cvp指向的條件變量阻塞的線程退出阻塞狀態。在 同一個互斥鎖的保護下使用cond_signal()。否則,條件變量可以在對關聯條件變量 的測試和cond_wait()帶來的阻塞之間獲得信號,這將導致無限期的等待。
如果沒有一個線程關于條件變量阻塞,cond_signal無效。
返回值--cond_signal()在成功執行后返回零。其他值意味著錯誤。在以下情況發生時,函數失敗并返回相關值。
EFAULT cvp指向一個非法地址。
Code Example 3-8 使用cond_wait(3T)和cond_signal(3T)的例子
Mutex_t count_lock;
Cond_t count_nonzero;
Unsigned int count;
Decrement_count()
{
mutex_lock(&count_lock);
while(count==0)
cond_wait(&count_nonzero,&count_lock);
count=count-1;
mutex_unlock(&count_lock);
}
increment_count()
{
mutex_lock(&count_lock);
if(count==0)
cond_signal(&count_nonzero);
count=count+1;
mutex_unlock(&count_lock);
}

3.2.4阻塞直到指定事件發生

cond_timedwait(3T)
#include (or #include )
int cond_timedwait(cond_t *cvp, mutex_t *mp,
timestruc_t *abstime);
cond_timedwait()和cond_wait()用法相似,差別在于cond_timedwait()在經過有abstime指定的時間時不阻塞。
即使是返回錯誤,cond_timedwait()也只在給互斥鎖加鎖后返回。
Cond_timedwait()函數阻塞,直到條件變量獲得信號或者經過由abstime指定 的時間。Time-out被指定為一天中的某個時間,這樣條件可以在不重新計算 time-out值的情況下被有效地重新測試,???就象在示例3-9中那樣。
返回值--cond_timedwait()在成功執行后返回零。其他值意味著錯誤。在以下情況發生時,函數失敗并返回相關值。
EINVAL 由abstime 指定的時間大于應用程序啟動的時間加50,000,000,或者納秒數大于等于1,000,000,000。
EFAULT cvp指向一個非法地址。
EINTR 等待被信號或fork()中斷。
ETIME abstime指定的時間已過。
Code Example 3-9 時間條件等待
Timestruc_t to;
Mutex_t m;
Cond_t c;
Mutex_lock(&m);
To.tv_sec=time(NULL)+TIMEOUT;
To.tv_nsec=0;
While (cond==FALSE){
Err=cond_timedwait(&c,&m,&to);
If(err=ETIME) {
/* TIMEOUT, do something */
break;
}
}
mutex_unlock(&m);

3.2.5使所有線程退出阻塞狀態

cond_broadcast(3T)
#include ( or #include )
int cond_wait(cond_t *cvp);
用cond_broadcast()使得所有關于由cvp指向的條件變量阻塞的線程退出阻塞狀態。如果沒有阻塞的線程,cond_broadcast()無效。
這個函數喚醒所有由cond_wait()阻塞的線程。因為所有關于條件變量阻塞的線程都同時參與競爭,所以使用這個函數需要小心。
例如,用cond_broadcast()使得線程競爭變量資源,如示例3-10所示。
Code Example 3-10 條件變量廣播
Mutex_t rsrc_lock;
Cond_t rsrc_add;
Unsigned int resources;

Get_resources(int amount)
{ mutex_lock(&rsrc_lock);
while(resources < amount) {
cond_wait(&rsrc_add, &rsrc_lock);
}
resources-=amount;
mutex_unlock(&rsrc_lock);
}
add_resources(int amount)
{
mutex_lock(&rsrc_lock);
resources +=amount;
cond_broadcast(&rsrc_add);
mutex_unlock(&rsrc_lock);
}
注意,在互斥鎖的保護內部,首先調用cond_broadcast()或者首先給resource增值,效果是一樣的。
返回值--cond_broadcast()在成功執行后返回零。其他值意味著錯誤。在以下情況發生時,函數失敗并返回相關值。
EFAULT cvp指向一個非法地址。
在互斥鎖的保護下調用cond_broadcast()。否則,條件變量可能在檢驗關聯狀態和通過cond_wait()之間獲得信號,這將導致永久等待。

3.2.6清除條件變量

cond_destroy(3T)
#include ( or #include )
int cond_destroy(cond_t *cvp);
使用cond_destroy() 破壞由cvp指向的條件變量的任何狀態。但是儲存條件變量的空間將不被釋放。
返回值--cond_destroy()在成功執行后返回零。其他值意味著錯誤。在以下情況發生時,函數失敗并返回相關值。
EFAULT cvp指向一個非法地址。

3.2.7喚醒丟失問題

在沒有互斥鎖保護的情況下調用cond_signal()或者cond_broadcast()會導致丟 失喚醒問題。一個喚醒丟失發生在信號或廣播已經發出,但是線程即使在條件為真 時仍然關于條件變量阻塞,具體地說,這發生在調用cond_signal()時并沒有獲得互 斥鎖的情況下。
如果一個線程已經作過條件檢驗,但是尚未調用cond_wait(),這時另外一個線 程調用cond_signal(),因為沒有已被阻塞的線程,喚醒信號丟失。
3.2.8生產者/消費者問題

這個問題是一個標準的、著名的同時性編程問題的集合:一個有限緩沖區和兩類線程,生產者和消費者,他們分別把產品放入緩沖區和從緩沖區中拿走產品。
一個生產者在緩沖區滿時必須等待,消費者在緩沖區空時必須等待。
一個條件變量代表了一個等待條件的線程隊列。
示例3-11有兩個隊列,一個(less)給生產者,它們等待空的位置以便放入信 息;另外一個(more)給消費者,它們等待信息放入緩沖區。這個例子也有一個互 斥鎖,它是一個結構,保證同時只有一個線程可以訪問緩沖區。
下面是緩沖區數據結構的代碼。
Code Example 3-11 生產者/消費者問題和條件變量
Typedef struct{
Char buf[BSIZE];
Int occupled;
Int nextin;
Int nextout;
Mutex_t mutex;
Cond_t more;
Cond_t less;
}buffer_t;
buffer_t buffer;
如示例3-12所示,生產者用一個互斥鎖保護緩沖區數據結構然后確定有足夠的空 間來存放信息。如果沒有,它調用cond_wait(),加入關于條件變量less阻塞的線程 隊列,說明緩沖區已滿。這個隊列需要被信號喚醒。
同時,作為cond_wait()的一部分,線程釋放互斥鎖。等待的生產者線程依賴于 消費者線程來喚醒。當條件變量獲得信號,等待less的線程隊列里的第一個線程被喚 醒。但是,在線程從cond_wait()返回前,必須獲得互斥鎖。
這再次保證了線程獲得對緩沖區的唯一訪問權。線程一定要檢測緩沖區有足夠的 空間,如果有的話,它把信息放入下一個可用的位置里。
同時,消費者線程也許正在等待有信息放入緩沖區。這些線程等待條件變量more。 一個生產者線程,在剛剛把信息放入存儲區后,調用cond_signal()來喚醒下一個等 待的消費者。(如果沒有等待的消費者,這個調用無效。)最后,生產者線程釋放互 斥鎖,允許其他線程操作緩沖區。

Code Example 3-12 生產者/消費者問題--生產者
Void producer(buffer_t *b, char item) {
Mutex_lock(&b->mutex);

While ( b->occupied >= BSIZE)
Cond_wait(&b->less, &b->mutex);
Assert(b->occupied < BSIZE);
b->buf(b->nextin++)=item;
b->nextin %=BSIZE;
b->occupied ++;
/* now: either b->occupied < BSIZE and b->nextin is the index
of the next empty slot in the buffer, or
b->occupied == BSIZE and b->nextin is the index of the
next (occupied) slot that will be emptied by a consumer
(such as b-> == b->nextout) */

cond_signal(&b->more);
mutex_unlock(&b->mutex);
}
注意assert()命令的用法;除非代碼用NDEBUG方式編譯,assert()在參數為真時 (非零值)不做任何操作,如果參數為假(參數為假),程序退出。
這種聲明在多線程編程中特別有用--在失敗時它們會立刻指出運行時的問題, 它們還有其他有用的特性。
后面說明代碼可以更加稱得上是聲明,但它太過復雜,無法用布爾表達式來表達,所以用文字來寫。???
聲明和說明???都是不變量的實例。它們都是一些邏輯命題,在程序正常執行時不應當被證偽,除非一個線程試圖改變非變量說明段的變量。???
不變量是一種極為有用的技術。即使它們沒有在程序中寫出,在分析程序中也需要把它們看成不變量。
生產者代碼中的不變量(說明部分)在程序執行到這一段時一定為真。如果你把這段說明移到mutex_unlock()后面,它將不一定保持為真。如果將其移到緊跟著聲明的后面,它仍然為真。
關鍵在于,不變量表現了一個始終為真的屬性,除非一個生產者或一個消費者正 在改變緩沖區的狀態。如果一個線程正在操作緩沖區(在互斥鎖的保護下),它將暫 時將不變量置為假。但是,一旦線程結束對緩沖區的操作,不變量會立刻恢復為真。
示例3-13為消費者的代碼。它的流程和生產者是對稱的。
Code Example 3-13 生產者/消費者問題--消費者
Char consumer(buffer_t *b){
Char item;
Mutex_lock(&b->mutex);
While(b->occupied <=0)
Cond_wait(&b->more, &b->mutex);
Assert(b->occupied>0);
Item=b->buf(b->nextout++);
b->nextout %=BSIZE;
b->occupied--;
/* now: either b->occupied>0 and b->nextout is the index of
the nexto ccupied slot in the buffer, or b->occupied==0
and b->nextout is the index of the next(empty) slot that
will be filled by a producer (such as b->nextout ==b->nextin) */
cond_signal(&b->less);
mutex_unlock(&b->mutex);
return(item);
}

3.3多讀單寫鎖

讀寫鎖允許多個線程同時進行讀操作,但一個時間至多只有一個線程進行寫操作。
表3-3 讀寫鎖的函數
函數 操作
rwlock_init(3T) 初始化一個讀寫鎖
rw_rdlock(3T) 獲得一個讀鎖
rw_tryrdlock(3T) 試圖獲得一個讀鎖
rw_wrlock(3T) 獲得一個寫鎖
rw_trywrlock(3T) 試圖獲得一個寫鎖
rw_unlock(3T) 使一個讀寫鎖退出阻塞
rwlock_destroy(3T) 清除讀寫鎖狀態
如果任何線程擁有一個讀鎖,其他線程也可以擁有讀鎖,但必須等待寫鎖。如 果一個線程擁有寫鎖,或者正在等待獲得寫鎖,其它線程必須等待獲得讀鎖或寫鎖。
讀寫鎖比互斥鎖要慢,但是在所保護的數據被頻繁地讀但并不頻繁寫的時候可以提高效率。
如果兩個進程有共享的可讀寫的內存,可以在初始化時設置成用讀寫鎖進行進程間的線程同步。
讀寫鎖使用前一定要初始化。

3.3.1初始化一個讀寫鎖
rwlock_init(3T)
#include (or #include )
int rwlock_init(rwlock_t *rwlp, int type, void * arg);
用rwlock_init()來初始化由rwlp指向的讀寫鎖并且設置鎖的狀態為沒有鎖。
Type可以是如下值之一(arg現在先不談)。
USYNC_PROCESS 讀寫鎖可以實現進程間的線程同步。
USYNC_THREAD 讀寫鎖只能在進程內部實現線程同步。
多線程不能同時初始化一個讀寫鎖。讀寫鎖可以通過分配零內存來初始化,在這種情況下,一定要設置USYNC_THREAD。一個讀寫鎖在使用當中不能被其他線程重新初始化。
返回值--rwlock_init()在成功執行后返回零。其他值意味著錯誤。在以下情況發生時,函數失敗并返回相關值。
EINVAL 非法參數。
EFAULT rwlp或arg指向一個非法地址。

3.3.2獲得一個讀鎖

rw_rdlock(3T)
#include (or #include )
int rw_rdlock(rwlock_t *rwlp);
用rw_rdlock()來給一個由rwlp指向的讀寫鎖加上讀鎖。如果讀寫鎖已經被加寫鎖,則調用線程阻塞直到寫鎖被釋放。否則,讀鎖將被成功獲得。
返回值--rw_rdlock()在成功執行后返回零。其他值意味著錯誤。在以下情況發生時,函數失敗并返回相關值。
EINVAL 非法參數。
EFAULT rwlp指向一個非法地址。

3.3.3試圖獲得一個讀鎖

rw_tryrdlock(3T)
#include (or #include )
int rw_tryrdlock(rwlock_t *rwlp);
試圖給讀寫鎖加讀鎖,如果讀寫鎖已經被加寫鎖,則返回錯誤,而不再進入阻塞狀態。否則,讀鎖將被成功獲得。
返回值--rw_tryrdlock ()在成功執行后返回零。其他值意味著錯誤。在以下情況發生時,函數失敗并返回相關值。
EINVAL 非法參數。
EFAULT rwlp指向一個非法地址。
EBUSY 由rwlp指向的讀寫鎖已經被加寫鎖。

3.3.4獲得一個寫鎖

rw_wrlock(3T)
#include (or #include )
int rw_wrlock(rwlock_t *rwlp);
用rw_wrlock()為由rwlp指向的讀寫鎖加寫鎖。如果該讀寫鎖已經被加讀鎖或寫鎖,則調用線程阻塞,直到所有鎖被釋放。一個時刻只有一個線程可以獲得寫鎖。
返回值--rw_wrlock ()在成功執行后返回零。其他值意味著錯誤。在以下情況發生時,函數失敗并返回相關值。
EINVAL 非法參數。
EFAULT rwlp指向一個非法地址。

3.3.5試圖獲得寫鎖

rw_trywrlock(3T)
#include (or #include )
int rw_trywrlock(rwlock_t *rwlp);
用rw_trywrlock()試圖獲得寫鎖,如果該讀寫鎖已經被加讀鎖或寫鎖,它將返回錯誤。
返回值--rw_trywrlock ()在成功執行后返回零。其他值意味著錯誤。在以下情況發生時,函數失敗并返回相關值。
EINVAL 非法參數。
EFAULT rwlp指向一個非法地址。
EBUSY 由rwlp指向的讀寫鎖已被加鎖。

3.3.6使一個讀寫鎖退出阻塞狀態

rw_unlock(3T)
#include (or #include )
int rwlock_tryrdlock(rwlock_t *rwlp);
用rw_unlock()來使由rwlp指向的讀寫鎖退出阻塞狀態。調用線程必須已經獲得對該讀寫鎖的讀鎖或寫鎖。如果任何其它線程在等待讀寫鎖可用,它們當中的一個將退出阻塞狀態。
返回值--rw_unlock ()在成功執行后返回零。其他值意味著錯誤。在以下情況發生時,函數失敗并返回相關值。
EINVAL 非法參數。
EFAULT rwlp指向一個非法地址。

3.3.7清除讀寫鎖

rwlock_destroy(3T)
#include (or #include )
int rwlock_destroy(rwlock_t *rwlp);
使用rwlock_destroy()來取消由rwlp指向的讀寫鎖的狀態。存儲讀寫鎖的空間不被釋放。
返回值--rw_destroy ()在成功執行后返回零。其他值意味著錯誤。在以下情況發生時,函數失敗并返回相關值。
EINVAL 非法參數。
EFAULT rwlp指向一個非法地址。
示例3-14用一個銀行帳戶來演示讀寫鎖。如果一個程序允許多個線程同時進行讀操作,一個時刻只有一個寫操作被允許。注意get_balance()函數通過鎖來保證檢查和儲存操作是原子操作。
Code Example 3-14 讀/寫銀行帳戶
Rwlock_t account_lock;
Float checking_balance=100.0;
Float saving_balance=100.0;
… …
rwlock_init (&account_lock, 0, NULL);
… …
float get_balance(){
float bal;
rw_rdlock(&account_lock);
bal=checking_balance +saving_balance;
rw_unlock(&account_lock);
return(bal);
}
void tranfer_checking_to_savings(float amount) {
rw_wrlock(&account_lock);
checking_balance=checking_balance - amount;
savings_balance=savings_balance +amount;
rw_unlock(&account_lock);
}

3.4信號量(信號燈)

信號燈是E.W.Dijkstra在60年代晚期定義的程序結構。Dijkstra的模型是一個鐵路上的操作:一段單線鐵路在一個時刻只允許一列火車通過。
用一個信號燈來維護這段鐵路。一列火車在進入單線鐵路之前必須等待信號燈 的許可。如果一列火車進入這段軌道,信號燈改變狀態,以防止其他火車進入。在 火車離開這段軌道時,必須將信號燈復原,使得其他火車得以進入。
在信號燈的計算機版本中,一個信號燈一般是一個整數,稱之為信號量。一個 線程在被允許進行后對信號量做一個p操作。
P操作的字面意思是線程必須等到信號量的值為正(positive)才能繼續進行, 進行前先給信號量減1。當做完相關的操作時(相當于離開鐵軌),線程執行一個 v操作,即給信號量加1。這兩個操作必須具有不可中斷性,也叫不可分性,英文字 面為原子性(atomic),即他們不能被分成兩個子操作,在子操作之間還可以插入 其它線程的其他操作,這些操作可能改變信號量。在P操作中,信號量的值在被減之 前一定要為正(使得信號量在被減1之后不會為負)。
在P操作或V操作當中,操作不會互相干擾。如果兩個V操作要同時執行,則信號量的新值比原來大2。
記住P和V本身是什么意思已經不重要了,就象記住Dijkstra是荷蘭人一樣。但 是,如果引起了學者考證的興趣,P代表prolagen,一個由proberen de verlagen演 變來的合成詞,它的意思是"試圖減"。V代表verhogen,它的意思是"增加"。這些在 Dijkstra的技術筆記EWD 74中提到過。
Sema_wait(3T)和sema_post(3T)分別對應Dijkstra的P和V操作, sema_trywait(3T)是P操作的一個可選的形式,在P操作不能執行時,線程不會阻塞, 而是立刻返回一個非零值。
有兩種基本的信號量:二值信號量,其值只能是0或者1,和計數信號量,可以 是非負值。一個二值信號量在邏輯上相當于一個互斥鎖。
然而,盡管并不強制,互斥鎖應當被認為只能被擁有鎖的線程釋放,而"擁有信 號量的線程"這個概念是不存在的,任何線程都可以進行一個V操作 (或sema_post(3T))。
計數信號量的功能大概和與互斥鎖合用的條件變量一樣強大。在很多情況下, 采用信號量的程序比采用條件變量要簡單一些(如下面的例子所示)。
然而,如果一個互斥鎖和條件變量一起使用,有一個隱含的框架,程序的哪一 部分被保護是明顯的。在信號量則不然,它可以用同時性編程當中的go to 來調用, 它更適合用于那些結構性不強的,不精確的方面。

3.4.1計數信號量

在概念上,一個信號量是一個非負整數。信號量在典型情況下用來協調資源, 信號量一般被初始化為可用資源的數量。線程在假如資源是給計數器加1,在拿走資 源時給計數器減1,操作都具有原子性。
如果一個信號量的值變為0,表明已無可用資源,想要給信號量減1的操作必須 等到它為正時。
表3-4 信號量函數
函數 操作
Sema_init(3T) 初始化信號量
Sema_post(3T) 增加信號量
Sema_wait(3T) 關于信號量阻塞
Sema_trywait(3T) 減少信號量
Sema_destroy(3T) 破壞信號量的狀態
因為信號量不被哪個線程占有,它們可以用異步事件來通知(例如信號處理器)。 而且,因為信號量包含狀態,他們可以被異步使用???,而不用象條件變量那樣 一定要先獲得互斥鎖。
缺省情況下,等待信號量的多個線程退出阻塞的順序是不確定的。
信號量在使用前一定要初始化。

3.4.2初始化一個信號量

sema_init(3T)
#include (or #include )
int sema_init(sema_t *sp, unsigned int count, int type, void *arg);
sema_init用count的值來初始化由sp指向的信號量。Type可以是如下值之一(arg先不談)。
USYNC_PROCESS 信號量可以在進程間進行線程同步。只有一個進程需要初始化
信號量。Arg忽略。
USYNC_THREAD 信號量只能在進程內部進行線程同步。
多個線程不能同時初始化同一個信號量。一個信號量在使用中不能被其他線程重新初始化。
返回值--sema_init()在成功執行后返回零。其他值意味著錯誤。在以下情況發生時,函數失敗并返回相關值。
EINVAL 非法參數。
EFAULT sp或arg指向一個非法地址。

3.4.3給信號量增值

sema_post(3T)
#include (or #include )
int sema_destroy(sema_t *sp);
用sema_post()給由sp指向的信號量原子地(表示其不可分性,下同)增1,如果有其它線程關于信號量阻塞,其中一個退出阻塞狀態。
返回值--sema_post()在成功執行后返回零。其他值意味著錯誤。在以下情況發生時,函數失敗并返回相關值。
EINVAL 非法參數。
EFAULT sp指向一個非法地址。

3.4.4關于一個信號量阻塞

sema_wait(3T)
#include (or #include )
int sema_wait(sema_t *sp)
用sema_wait()使得調用線程在由sp指向的信號量小于等于零時阻塞,在其大于零原子地對其進行減操作。
返回值--sema_wait()在成功執行后返回零。其他值意味著錯誤。在以下情況發生時,函數失敗并返回相關值。
EINVAL 非法參數。
EFAULT sp指向一個非法地址。
EINTR 等待被信號或fork()打斷。

3.4.5給信號量減值

sema_trywait(3T)
#include (or #include )
int sema_trywait(sema_t *sp)
用sema_trywait()在sp比零大時對它進行原子地減操作。是sema_wait()的非阻塞版本。
返回值--sema_trywait()在成功執行后返回零。其他值意味著錯誤。在以下情況發生時,函數失敗并返回相關值。
EINVAL 非法參數。
EFAULT sp指向一個非法地址。
EBUSY sp 指向的值為零。

3.4.6清除信號量的狀態

sema_destroy(3T)
#include (or #include )
int sema_destroy(sema_t *sp)
用sema_destroy(3T)破壞與sp指向的信號量關聯的任何狀態,但空間不被釋放。
返回值--sema_destroy()在成功執行后返回零。其他值意味著錯誤。在以下情況發生時,函數失敗并返回相關值。
EINVAL 非法參數。
EFAULT sp指向一個非法地址。

3.4.7用信號量解決生產者/消費者問題

示例3-15所示的程序與條件變量的解決方案類似;兩個信號量代表空和滿的緩沖區的數目,生產者線程在沒有空緩沖區時阻塞,消費者在緩沖區全空時阻塞。
Code Example 3-15 用信號量解決的生產者/消費者問題
Typedef struct{
Char buf[BSIZE];
Sema_t occupied;
Sema_t empty;
Int nextin;
Int nextout;
Sema_t pmut;
Sema_t cmut;
} buffer_t;
buffer_t buffer;
sema_init(&buffer.occupied, 0, USYNC_THREAD, 0);
sema_init(&buffer.empty, BSIZE, USYNC_THREAD, 0);
sema_init(&buffer.pmut, 1, USYNC_THREAD, 0);
sema_init(&buffer.cmut, 1, USYNC_THREAD, 0);
buffer.nextin=buffer.nextout =0;
另外一對信號量與互斥鎖作用相同,用來在有多生產者和多個空緩沖區的情況下,或者是有多個消費者和多個滿的緩沖區的情況下控制對緩沖區的訪問。互斥鎖同樣可以工作,但這里主要是演示信號量的例子。
Code Example 3-16 生產者/消費者問題--生產者
Void producer(buffer_t *b, char item){
Sema_wait(&b->empty);
Sema_wait(&b->pmut);
b->buf[b->nextin]=item;
b->nextin++;
b->nextin %=BSIZE;
sema_post( &b->pmut);
sema_post(&b->occupied);
}
Code Example 3-17 生產者/消費者問題--消費者
Char consumer(buffer_t *b){
Char item;
Sema_wait(&b->occupied);
Sema_wait(&b->cmut);
Item=b->buf[b->nextout];
b->nextout++;
b->nextout %=BSIZE;
sema_post (&b->cmut);
sema_post(&b->empty):
return(item);
}

3.5進程間同步

四種同步原語中的任何一種都能做進程間的同步。只要保證同步變量在共享內存 段,并且帶USYNC_PROCESS參數來對其進行初始化。在這之后,對同步變量的使用和 USYNC_THREAD初始化后的線程同步是一樣的。

Mutex_init(&m, USYNC_PROCESS,0);
Rwlock_init(&rw, USYNC_PROCESS,0);
Cond_init(&cv,USYNC_PROCESS,0);
Sema_init(&s,count,USYNC_PROCESS,0);
示例3-18顯示了一個生產者/消費者問題,生產者和消費者在兩個不同的進程里。 主函數把全零的內存段映射到它的地址空間里。注意mutex_init()和cond_init()一 定要用type=USYNC_PROCESS來初始化。
子進程運行消費者,父進程運行生產者。
此例也顯示了生產者和消費者的驅動程序。生產者驅動producer_driver()簡單 地從stdin中讀字符并且調用生產者函數producer()。消費者驅動consumer_driver() 通過調用consumer()來讀取字符,并將其寫入stdout。
Code Example 3-18 生產者/消費者問題,用USYNC_PROCESS
Main(){
Int zfd;
Buffer_t * buffer;
Zfd=open("/dev/zero", O_RDWR);
Buffer=(buffer_t *)mmap(NULL, sizeof(buffer_t),
PROT_READ|PROT_WRITE, MAP_SHARED, zfd, 0);
Buffer->occupied=buffer->nextin=buffer->nextout=0;
Mutex_init(&buffer->lock, USYNC_PROCESS,0);
Cond_init(&buffer->less, USYNC_PROCESS, 0);
Cond_init(&buffer->more, USYNC_PROCESS, 0);
If(fork()==0)
Consumer_driver(buffer);
Else
Producer_driver(buffer);
}
void producer_driver(buffer_t *b){
int item;
while(1){
item=getchar();
if(item==EOF){
producer(b, '');
break;
} else
producer(b, (char)item);
}
}
void consumer_driver(buffer_t *b){
char item;
while (1) {
if ((item=consumer(b))=='')
break;
putchar(item);
}
}
一個子進程被創建出來運行消費者;父進程運行生產者。

3.6同步原語的比較

Solaris中最基本的同步原語是互斥鎖。所以,在內存使用和執行時它是最 有效的。對互斥鎖最基本的使用是對資源的依次訪問。
在Solaris中效率排第二的是條件變量。條件變量的基本用法是關于一個狀態 的改變而阻塞。在關于一個條件變量阻塞之前一定要先獲得互斥鎖,在從 cond_wait()返回且改變變量狀態后一定要釋放該互斥鎖。
信號量比條件變量占用更多的內存。因為信號量是作用于狀態,而不是控制 ???,所以在一些特定的條件下它更容易使用。和鎖不同,信號量沒有一個所 有者。任何線程都可以給已阻塞的信號量增值。
讀寫鎖是Solaris里最復雜的同步機制。這意味著它不象其他原語那樣細致 ???。一個讀寫鎖通常用在讀操作比寫操作頻繁的時候。

總結

以上是生活随笔為你收集整理的多线程编程指南的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

日韩欧美中文字幕在线三区 | 天堂无码人妻精品一区二区三区 | 97人妻精品一区二区三区 | 亚洲色欲色欲天天天www | 久久久久久亚洲精品a片成人 | 亚洲综合色区中文字幕 | 无码av中文字幕免费放 | 亚洲国产精品无码一区二区三区 | 亲嘴扒胸摸屁股激烈网站 | 免费中文字幕日韩欧美 | 人妻尝试又大又粗久久 | 亚洲呦女专区 | 2020久久超碰国产精品最新 | 国内综合精品午夜久久资源 | 国产精品无码一区二区桃花视频 | 少妇邻居内射在线 | 扒开双腿吃奶呻吟做受视频 | 成年美女黄网站色大免费视频 | 中文字幕av无码一区二区三区电影 | 亚洲精品一区二区三区婷婷月 | 亚洲成在人网站无码天堂 | 人妻少妇被猛烈进入中文字幕 | 国产小呦泬泬99精品 | 久久久精品欧美一区二区免费 | 国产xxx69麻豆国语对白 | 激情国产av做激情国产爱 | 国产激情精品一区二区三区 | 无码毛片视频一区二区本码 | 欧美 丝袜 自拍 制服 另类 | 成人欧美一区二区三区 | 免费无码的av片在线观看 | 欧美 丝袜 自拍 制服 另类 | 在线视频网站www色 | 日本精品少妇一区二区三区 | 国产精品毛多多水多 | 久久精品一区二区三区四区 | 日产精品99久久久久久 | 99精品国产综合久久久久五月天 | 清纯唯美经典一区二区 | 日韩精品无码免费一区二区三区 | 又大又硬又黄的免费视频 | 国产午夜精品一区二区三区嫩草 | 亚洲成av人在线观看网址 | 99久久精品午夜一区二区 | 欧美人与动性行为视频 | 亚洲中文字幕va福利 | 人人妻人人澡人人爽人人精品 | 日韩精品乱码av一区二区 | 日韩精品无码免费一区二区三区 | 亚洲精品国产第一综合99久久 | 国产suv精品一区二区五 | 三上悠亚人妻中文字幕在线 | 天天摸天天透天天添 | 一个人免费观看的www视频 | 日产精品99久久久久久 | 熟妇人妻无乱码中文字幕 | 亚洲 a v无 码免 费 成 人 a v | 国产成人综合美国十次 | 我要看www免费看插插视频 | 国产成人综合色在线观看网站 | 成 人 免费观看网站 | 欧美精品免费观看二区 | 无码纯肉视频在线观看 | 中文字幕av无码一区二区三区电影 | 国产福利视频一区二区 | 嫩b人妻精品一区二区三区 | 亚洲人成网站免费播放 | 黑人大群体交免费视频 | 亚洲日韩av片在线观看 | 狠狠综合久久久久综合网 | 无码任你躁久久久久久久 | 一本大道伊人av久久综合 | 无码人妻av免费一区二区三区 | 国产精品久免费的黄网站 | 日日天干夜夜狠狠爱 | 婷婷丁香五月天综合东京热 | 国产农村妇女高潮大叫 | 国产精品人妻一区二区三区四 | 天天躁夜夜躁狠狠是什么心态 | 日韩人妻系列无码专区 | 久久国产自偷自偷免费一区调 | 国产精品久久国产三级国 | 国产精品久久久久久无码 | 亚洲国精产品一二二线 | 一区二区传媒有限公司 | 无码人妻丰满熟妇区五十路百度 | www一区二区www免费 | 青青青手机频在线观看 | 熟女少妇人妻中文字幕 | 日本免费一区二区三区最新 | 波多野结衣一区二区三区av免费 | 亚洲一区二区三区含羞草 | 国产一精品一av一免费 | 日本一区二区三区免费播放 | 欧洲精品码一区二区三区免费看 | 一本无码人妻在中文字幕免费 | 黑人巨大精品欧美一区二区 | 国产一区二区三区四区五区加勒比 | 国产午夜精品一区二区三区嫩草 | 国产做国产爱免费视频 | 亚洲成av人综合在线观看 | 国产69精品久久久久app下载 | 国语自产偷拍精品视频偷 | 少妇久久久久久人妻无码 | 精品国产av色一区二区深夜久久 | 国内揄拍国内精品少妇国语 | 免费无码肉片在线观看 | 国产亚洲日韩欧美另类第八页 | 乱码午夜-极国产极内射 | 成人一在线视频日韩国产 | 国内少妇偷人精品视频 | 国产性生大片免费观看性 | 扒开双腿吃奶呻吟做受视频 | 四虎永久在线精品免费网址 | 一本久久a久久精品vr综合 | 中文字幕乱码亚洲无线三区 | 无码纯肉视频在线观看 | 人妻熟女一区 | 曰韩少妇内射免费播放 | 国产精品欧美成人 | 捆绑白丝粉色jk震动捧喷白浆 | 亚洲日韩一区二区三区 | 黑人粗大猛烈进出高潮视频 | 精品乱子伦一区二区三区 | 国精产品一品二品国精品69xx | 亚洲熟熟妇xxxx | 久久久久亚洲精品男人的天堂 | 一区二区三区乱码在线 | 欧洲 | 亚洲综合久久一区二区 | 无套内射视频囯产 | 精品国产一区二区三区av 性色 | 欧美怡红院免费全部视频 | 97久久精品无码一区二区 | 久在线观看福利视频 | 亚洲国产精品一区二区美利坚 | 真人与拘做受免费视频 | 色爱情人网站 | 女人和拘做爰正片视频 | 男女下面进入的视频免费午夜 | 国产精品无码久久av | 精品人妻中文字幕有码在线 | 成人片黄网站色大片免费观看 | 综合人妻久久一区二区精品 | 99久久婷婷国产综合精品青草免费 | 国产成人无码av一区二区 | 国产真实夫妇视频 | 中文字幕无线码 | 国产精品久久国产三级国 | 国产无遮挡吃胸膜奶免费看 | 无码人妻av免费一区二区三区 | 久久婷婷五月综合色国产香蕉 | 在线成人www免费观看视频 | 精品偷自拍另类在线观看 | 亚洲另类伦春色综合小说 | 99久久久国产精品无码免费 | 国产成人精品久久亚洲高清不卡 | 巨爆乳无码视频在线观看 | 夫妻免费无码v看片 | 性生交片免费无码看人 | 少妇一晚三次一区二区三区 | 中文字幕乱码中文乱码51精品 | 精品乱码久久久久久久 | 国产免费久久久久久无码 | 我要看www免费看插插视频 | 三级4级全黄60分钟 | 色综合久久久久综合一本到桃花网 | 国产精品久久久久久亚洲影视内衣 | 国产成人精品必看 | 久青草影院在线观看国产 | 国产成人人人97超碰超爽8 | 亚洲精品鲁一鲁一区二区三区 | 亚洲aⅴ无码成人网站国产app | 国产97人人超碰caoprom | 少妇性俱乐部纵欲狂欢电影 | 内射爽无广熟女亚洲 | 国产极品美女高潮无套在线观看 | 国产成人精品视频ⅴa片软件竹菊 | 高清国产亚洲精品自在久久 | 国产在热线精品视频 | 青青久在线视频免费观看 | 日韩欧美群交p片內射中文 | 内射欧美老妇wbb | 亚洲理论电影在线观看 | 偷窥村妇洗澡毛毛多 | 窝窝午夜理论片影院 | 双乳奶水饱满少妇呻吟 | 国产精品久久久久久久9999 | 久热国产vs视频在线观看 | 国产成人无码av片在线观看不卡 | 少妇一晚三次一区二区三区 | 天天拍夜夜添久久精品 | 桃花色综合影院 | 久久婷婷五月综合色国产香蕉 | 精品aⅴ一区二区三区 | 精品成在人线av无码免费看 | 99视频精品全部免费免费观看 | 久久久国产精品无码免费专区 | 国产成人无码一二三区视频 | 国产午夜福利亚洲第一 | 成人精品视频一区二区三区尤物 | 亚洲国产午夜精品理论片 | 亚洲精品成a人在线观看 | 玩弄中年熟妇正在播放 | 76少妇精品导航 | 少妇高潮喷潮久久久影院 | 日韩精品无码免费一区二区三区 | 亚洲精品综合一区二区三区在线 | 亚洲国产成人a精品不卡在线 | 人人妻人人澡人人爽欧美精品 | 国产成人无码一二三区视频 | 377p欧洲日本亚洲大胆 | 欧美激情一区二区三区成人 | 中国女人内谢69xxxx | 久久久中文久久久无码 | 欧美丰满熟妇xxxx性ppx人交 | 永久免费观看美女裸体的网站 | 亚洲中文字幕久久无码 | 精品偷自拍另类在线观看 | 性做久久久久久久免费看 | 97se亚洲精品一区 | 中文字幕+乱码+中文字幕一区 | 无码精品国产va在线观看dvd | 亚洲欧洲日本无在线码 | 亚洲人成无码网www | 丰满少妇弄高潮了www | 性史性农村dvd毛片 | 天堂无码人妻精品一区二区三区 | 国产9 9在线 | 中文 | 国産精品久久久久久久 | 清纯唯美经典一区二区 | 日日摸天天摸爽爽狠狠97 | 国产亲子乱弄免费视频 | 免费人成在线观看网站 | 国产乱人偷精品人妻a片 | 欧美日韩亚洲国产精品 | 色综合天天综合狠狠爱 | 自拍偷自拍亚洲精品被多人伦好爽 | 免费无码肉片在线观看 | 无码任你躁久久久久久久 | 麻豆国产97在线 | 欧洲 | 亚洲乱码日产精品bd | а天堂中文在线官网 | 无码任你躁久久久久久久 | 日韩欧美中文字幕在线三区 | 四虎永久在线精品免费网址 | 亚洲区欧美区综合区自拍区 | 性生交大片免费看女人按摩摩 | 亚洲小说春色综合另类 | 女人被男人躁得好爽免费视频 | 97精品国产97久久久久久免费 | 极品嫩模高潮叫床 | 亚洲中文字幕va福利 | 成人aaa片一区国产精品 | 国产办公室秘书无码精品99 | 欧美熟妇另类久久久久久不卡 | 国产精品视频免费播放 | 国产小呦泬泬99精品 | 丝袜 中出 制服 人妻 美腿 | 激情国产av做激情国产爱 | 欧美日本免费一区二区三区 | 国产绳艺sm调教室论坛 | 最近免费中文字幕中文高清百度 | 精品久久久久香蕉网 | 国产熟妇另类久久久久 | 成人无码视频在线观看网站 | 暴力强奷在线播放无码 | 亚洲精品一区二区三区大桥未久 | 女人被男人躁得好爽免费视频 | 国产农村乱对白刺激视频 | 亚洲精品中文字幕乱码 | 日韩人妻系列无码专区 | 亚洲欧美色中文字幕在线 | 夜夜高潮次次欢爽av女 | 无码国产激情在线观看 | 国产精品久久久午夜夜伦鲁鲁 | av无码不卡在线观看免费 | 娇妻被黑人粗大高潮白浆 | 国产亚洲精品久久久久久久 | 精品欧洲av无码一区二区三区 | 色一情一乱一伦一区二区三欧美 | 丝袜人妻一区二区三区 | 久久人人97超碰a片精品 | 欧美日韩在线亚洲综合国产人 | 色欲久久久天天天综合网精品 | 免费中文字幕日韩欧美 | 性啪啪chinese东北女人 | 波多野结衣av一区二区全免费观看 | 一区二区传媒有限公司 | 无码国产激情在线观看 | 国产真实伦对白全集 | 领导边摸边吃奶边做爽在线观看 | 爆乳一区二区三区无码 | 扒开双腿吃奶呻吟做受视频 | av无码电影一区二区三区 | 精品国产麻豆免费人成网站 | 亚洲精品一区二区三区大桥未久 | 无码播放一区二区三区 | 国产成人无码午夜视频在线观看 | 1000部夫妻午夜免费 | 国产精品国产三级国产专播 | 国产乱人偷精品人妻a片 | 国产人妻人伦精品1国产丝袜 | 亚洲色在线无码国产精品不卡 | 男女超爽视频免费播放 | 亚洲国产精品成人久久蜜臀 | 搡女人真爽免费视频大全 | 国产在线精品一区二区高清不卡 | 少妇厨房愉情理9仑片视频 | 久久精品国产大片免费观看 | 97精品国产97久久久久久免费 | 国精产品一区二区三区 | 麻豆md0077饥渴少妇 | 一本色道久久综合亚洲精品不卡 | 十八禁真人啪啪免费网站 | 蜜臀av无码人妻精品 | 国产乱人偷精品人妻a片 | 人人妻人人藻人人爽欧美一区 | 精品国产福利一区二区 | 国产熟妇高潮叫床视频播放 | 麻豆国产丝袜白领秘书在线观看 | 在线观看国产午夜福利片 | 东京热无码av男人的天堂 | 国产农村妇女高潮大叫 | 噜噜噜亚洲色成人网站 | 国产疯狂伦交大片 | 丝袜 中出 制服 人妻 美腿 | 亚洲男人av天堂午夜在 | 水蜜桃色314在线观看 | 无码一区二区三区在线观看 | 国产一区二区三区影院 | 国産精品久久久久久久 | 特黄特色大片免费播放器图片 | 亚洲国产av精品一区二区蜜芽 | 桃花色综合影院 | 日韩精品成人一区二区三区 | 亚欧洲精品在线视频免费观看 | 国产69精品久久久久app下载 | 激情内射日本一区二区三区 | 成人片黄网站色大片免费观看 | 中文字幕色婷婷在线视频 | 牛和人交xxxx欧美 | 啦啦啦www在线观看免费视频 | 男人的天堂2018无码 | 美女黄网站人色视频免费国产 | 久久亚洲国产成人精品性色 | 中文字幕无码日韩欧毛 | 免费乱码人妻系列无码专区 | 成人欧美一区二区三区黑人免费 | 亚洲中文字幕乱码av波多ji | 亚洲国产精品毛片av不卡在线 | www国产亚洲精品久久网站 | 亚洲成av人综合在线观看 | 亚洲日韩中文字幕在线播放 | 国产色在线 | 国产 | 国产人妻大战黑人第1集 | 久久午夜夜伦鲁鲁片无码免费 | 中文字幕人妻无码一区二区三区 | 日本爽爽爽爽爽爽在线观看免 | 国产尤物精品视频 | 无码国内精品人妻少妇 | 亚洲人成网站免费播放 | 免费视频欧美无人区码 | 少妇邻居内射在线 | 亚洲 欧美 激情 小说 另类 | 中文字幕无码免费久久99 | 1000部夫妻午夜免费 | 亚洲成在人网站无码天堂 | av无码电影一区二区三区 | 久久亚洲国产成人精品性色 | 久久精品国产大片免费观看 | 国产精品.xx视频.xxtv | 无套内射视频囯产 | 国产电影无码午夜在线播放 | 夜夜高潮次次欢爽av女 | 丰满护士巨好爽好大乳 | 亚洲日韩av一区二区三区四区 | 久久久av男人的天堂 | 狠狠噜狠狠狠狠丁香五月 | 亚洲毛片av日韩av无码 | 国产精品无码一区二区桃花视频 | 精品偷自拍另类在线观看 | 我要看www免费看插插视频 | 久久精品丝袜高跟鞋 | 狠狠色噜噜狠狠狠7777奇米 | 亚洲国产精品久久久久久 | 久久国产精品偷任你爽任你 | 色欲久久久天天天综合网精品 | 精品水蜜桃久久久久久久 | 精品乱子伦一区二区三区 | 亚洲精品综合五月久久小说 | 欧美黑人性暴力猛交喷水 | 国产乱人无码伦av在线a | 国产sm调教视频在线观看 | 国产99久久精品一区二区 | 欧美亚洲日韩国产人成在线播放 | 色情久久久av熟女人妻网站 | 蜜桃av抽搐高潮一区二区 | 少妇人妻偷人精品无码视频 | 久久亚洲a片com人成 | 性色欲情网站iwww九文堂 | 永久免费精品精品永久-夜色 | 人妻插b视频一区二区三区 | 亚洲第一无码av无码专区 | 日韩无码专区 | 亚洲の无码国产の无码影院 | 欧美日韩在线亚洲综合国产人 | 夜精品a片一区二区三区无码白浆 | 欧美亚洲国产一区二区三区 | 久久综合狠狠综合久久综合88 | 国产成人无码av片在线观看不卡 | 国产做国产爱免费视频 | 成人无码视频在线观看网站 | 我要看www免费看插插视频 | 亚洲精品国产品国语在线观看 | 亚洲区欧美区综合区自拍区 | аⅴ资源天堂资源库在线 | 国产午夜福利100集发布 | 理论片87福利理论电影 | 正在播放东北夫妻内射 | 特大黑人娇小亚洲女 | 日本熟妇浓毛 | 久久亚洲日韩精品一区二区三区 | 午夜熟女插插xx免费视频 | 丰满少妇女裸体bbw | 亚洲熟悉妇女xxx妇女av | 成人综合网亚洲伊人 | 一本一道久久综合久久 | 日韩无套无码精品 | 精品国产青草久久久久福利 | 一本久道久久综合狠狠爱 | 精品国精品国产自在久国产87 | 成人无码影片精品久久久 | 亚洲精品午夜国产va久久成人 | 自拍偷自拍亚洲精品被多人伦好爽 | 日韩人妻无码一区二区三区久久99 | 国产真实伦对白全集 | www国产亚洲精品久久久日本 | 99精品无人区乱码1区2区3区 | 2020久久香蕉国产线看观看 | 日本一卡2卡3卡四卡精品网站 | 亚洲欧美日韩综合久久久 | 牲欲强的熟妇农村老妇女视频 | 在线成人www免费观看视频 | 性做久久久久久久久 | 国产精品99爱免费视频 | 精品一区二区三区波多野结衣 | 一区二区传媒有限公司 | 美女黄网站人色视频免费国产 | 人人妻人人澡人人爽人人精品 | 任你躁国产自任一区二区三区 | 狠狠色丁香久久婷婷综合五月 | 成人性做爰aaa片免费看不忠 | 国产女主播喷水视频在线观看 | 野外少妇愉情中文字幕 | 亚洲欧美日韩国产精品一区二区 | 亚无码乱人伦一区二区 | 老头边吃奶边弄进去呻吟 | 国产精品理论片在线观看 | 久久综合色之久久综合 | 久久午夜夜伦鲁鲁片无码免费 | 一个人免费观看的www视频 | 天天躁日日躁狠狠躁免费麻豆 | 国产精品永久免费视频 | 丰满护士巨好爽好大乳 | 国产农村妇女高潮大叫 | 一本色道婷婷久久欧美 | 国产熟妇高潮叫床视频播放 | 欧美freesex黑人又粗又大 | 日本一卡2卡3卡4卡无卡免费网站 国产一区二区三区影院 | 欧美喷潮久久久xxxxx | 国产偷自视频区视频 | 无码中文字幕色专区 | 性生交大片免费看女人按摩摩 | 丝袜足控一区二区三区 | 十八禁真人啪啪免费网站 | 一个人看的视频www在线 | 午夜福利不卡在线视频 | 超碰97人人射妻 | 欧美日韩综合一区二区三区 | 国内精品人妻无码久久久影院 | 国产av人人夜夜澡人人爽麻豆 | 九九在线中文字幕无码 | 精品水蜜桃久久久久久久 | 欧美激情一区二区三区成人 | 人人澡人摸人人添 | 精品日本一区二区三区在线观看 | 久久成人a毛片免费观看网站 | 疯狂三人交性欧美 | 国产人妻精品一区二区三区不卡 | 午夜精品一区二区三区在线观看 | 亚洲精品国偷拍自产在线观看蜜桃 | 狠狠色欧美亚洲狠狠色www | 婷婷色婷婷开心五月四房播播 | 久久精品国产99久久6动漫 | 丁香啪啪综合成人亚洲 | 97精品国产97久久久久久免费 | 18无码粉嫩小泬无套在线观看 | 天堂在线观看www | 亚洲精品国产a久久久久久 | 无码任你躁久久久久久久 | 久久久久99精品成人片 | 久久久久久久人妻无码中文字幕爆 | 熟女体下毛毛黑森林 | www国产亚洲精品久久久日本 | 欧美日韩一区二区三区自拍 | 成人精品视频一区二区三区尤物 | 久久精品视频在线看15 | 国产精品丝袜黑色高跟鞋 | 欧美三级不卡在线观看 | 中文字幕乱码人妻二区三区 | 亚洲欧美精品aaaaaa片 | 网友自拍区视频精品 | 色综合视频一区二区三区 | 欧美猛少妇色xxxxx | 人人超人人超碰超国产 | 国产性猛交╳xxx乱大交 国产精品久久久久久无码 欧洲欧美人成视频在线 | 荡女精品导航 | 国产农村妇女aaaaa视频 撕开奶罩揉吮奶头视频 | 伊人久久大香线蕉午夜 | 国内精品人妻无码久久久影院蜜桃 | 成人欧美一区二区三区黑人 | 久久久久久久久888 | 无套内射视频囯产 | 精品久久综合1区2区3区激情 | 老头边吃奶边弄进去呻吟 | 荫蒂被男人添的好舒服爽免费视频 | 无码人妻丰满熟妇区五十路百度 | 亚洲无人区午夜福利码高清完整版 | 日产精品高潮呻吟av久久 | 免费国产成人高清在线观看网站 | 成人无码视频在线观看网站 | 亚洲成熟女人毛毛耸耸多 | 亚洲欧美日韩成人高清在线一区 | 欧美放荡的少妇 | 亚洲精品国产品国语在线观看 | 欧美日韩在线亚洲综合国产人 | 国产精品99久久精品爆乳 | 色综合久久网 | 久久精品一区二区三区四区 | 少妇人妻av毛片在线看 | 亚洲熟悉妇女xxx妇女av | 少妇的肉体aa片免费 | 国产精品亚洲а∨无码播放麻豆 | 黑人巨大精品欧美一区二区 | √天堂中文官网8在线 | 亚洲一区二区三区含羞草 | 国产明星裸体无码xxxx视频 | 超碰97人人做人人爱少妇 | 丰满少妇人妻久久久久久 | 正在播放东北夫妻内射 | 精品aⅴ一区二区三区 | 日韩在线不卡免费视频一区 | www国产亚洲精品久久久日本 | 精品久久综合1区2区3区激情 | 天天躁日日躁狠狠躁免费麻豆 | 国产农村妇女aaaaa视频 撕开奶罩揉吮奶头视频 | 欧美激情一区二区三区成人 | 性色av无码免费一区二区三区 | аⅴ资源天堂资源库在线 | 2020久久超碰国产精品最新 | 亚洲欧洲中文日韩av乱码 | 人妻无码αv中文字幕久久琪琪布 | 中文字幕色婷婷在线视频 | 一本大道久久东京热无码av | 欧美日韩色另类综合 | 国产真实伦对白全集 | 美女极度色诱视频国产 | 色一情一乱一伦一视频免费看 | 成人av无码一区二区三区 | aa片在线观看视频在线播放 | 成熟妇人a片免费看网站 | 精品国偷自产在线视频 | 人人妻人人澡人人爽欧美一区九九 | 亚洲精品久久久久久久久久久 | 久久精品国产一区二区三区肥胖 | 精品 日韩 国产 欧美 视频 | 狠狠色丁香久久婷婷综合五月 | 性生交大片免费看l | 国产精品毛多多水多 | 色一情一乱一伦 | 白嫩日本少妇做爰 | 西西人体www44rt大胆高清 | 无码人妻av免费一区二区三区 | 久久久久成人精品免费播放动漫 | 亚洲熟妇色xxxxx欧美老妇y | 男女超爽视频免费播放 | 国产成人午夜福利在线播放 | 亚洲爆乳大丰满无码专区 | 亚洲精品一区二区三区四区五区 | √天堂资源地址中文在线 | 欧美刺激性大交 | 亚欧洲精品在线视频免费观看 | 国产精品亚洲а∨无码播放麻豆 | 国产精品第一国产精品 | 日韩av无码一区二区三区不卡 | 亚洲综合久久一区二区 | 午夜成人1000部免费视频 | 麻豆精产国品 | 中文字幕无码视频专区 | 国产日产欧产精品精品app | 荫蒂被男人添的好舒服爽免费视频 | 国内揄拍国内精品少妇国语 | 欧美日本免费一区二区三区 | 中文字幕无码日韩欧毛 | 久久久久国色av免费观看性色 | 国产精品无码mv在线观看 | 亚洲毛片av日韩av无码 | 蜜桃视频韩日免费播放 | 国语自产偷拍精品视频偷 | 好男人www社区 | 台湾无码一区二区 | 好屌草这里只有精品 | 狠狠色欧美亚洲狠狠色www | 蜜桃视频插满18在线观看 | 午夜精品久久久久久久久 | 午夜无码区在线观看 | 国内精品九九久久久精品 | 最近免费中文字幕中文高清百度 | 波多野结衣av一区二区全免费观看 | 中文亚洲成a人片在线观看 | 内射欧美老妇wbb | 一区二区三区乱码在线 | 欧洲 | 日本乱偷人妻中文字幕 | 亚洲一区二区三区国产精华液 | 国产av一区二区三区最新精品 | 天堂一区人妻无码 | 婷婷六月久久综合丁香 | 亚洲熟妇自偷自拍另类 | 免费看少妇作爱视频 | 国产黄在线观看免费观看不卡 | 亚洲国产成人a精品不卡在线 | 精品无码一区二区三区的天堂 | 帮老师解开蕾丝奶罩吸乳网站 | 欧美人与动性行为视频 | 国产尤物精品视频 | 亚洲欧美日韩综合久久久 | 无码中文字幕色专区 | 国产亚洲日韩欧美另类第八页 | 亚洲狠狠婷婷综合久久 | 亚洲欧洲日本综合aⅴ在线 | 香港三级日本三级妇三级 | 2020久久超碰国产精品最新 | 一区二区三区乱码在线 | 欧洲 | 又湿又紧又大又爽a视频国产 | 国产真人无遮挡作爱免费视频 | 欧美精品国产综合久久 | 偷窥村妇洗澡毛毛多 | 午夜性刺激在线视频免费 | 黑人玩弄人妻中文在线 | 亚洲国产精品久久人人爱 | 内射白嫩少妇超碰 | 国产电影无码午夜在线播放 | 久久www免费人成人片 | 亚洲国产精品久久久天堂 | 爆乳一区二区三区无码 | 久久久久久a亚洲欧洲av冫 | 岛国片人妻三上悠亚 | 中文字幕无码免费久久9一区9 | 牲交欧美兽交欧美 | 亚洲 激情 小说 另类 欧美 | 国产成人精品必看 | 亚洲精品成人福利网站 | 成 人 免费观看网站 | 玩弄少妇高潮ⅹxxxyw | 性色欲情网站iwww九文堂 | 国产亚洲精品精品国产亚洲综合 | 中国女人内谢69xxxx | 四十如虎的丰满熟妇啪啪 | 麻豆国产人妻欲求不满 | 无码纯肉视频在线观看 | 国产亚洲精品久久久久久久久动漫 | 久久国产精品偷任你爽任你 | 国産精品久久久久久久 | 亚洲中文无码av永久不收费 | 国产va免费精品观看 | 日本爽爽爽爽爽爽在线观看免 | 精品一区二区三区波多野结衣 | 成年美女黄网站色大免费视频 | 免费乱码人妻系列无码专区 | 国产av一区二区精品久久凹凸 | 国产舌乚八伦偷品w中 | 日本va欧美va欧美va精品 | 免费播放一区二区三区 | 两性色午夜免费视频 | 18精品久久久无码午夜福利 | 人人超人人超碰超国产 | 性欧美大战久久久久久久 | 丝袜 中出 制服 人妻 美腿 | 久激情内射婷内射蜜桃人妖 | 国产成人综合美国十次 | 国产精品亚洲综合色区韩国 | 久久99久久99精品中文字幕 | 国产精华av午夜在线观看 | 免费人成网站视频在线观看 | 无码中文字幕色专区 | 成人动漫在线观看 | 日韩精品乱码av一区二区 | 欧美成人免费全部网站 | 亚洲国产精品无码一区二区三区 | 日本丰满熟妇videos | 色婷婷av一区二区三区之红樱桃 | 人人爽人人爽人人片av亚洲 | 人人妻人人澡人人爽精品欧美 | 麻豆精产国品 | 精品夜夜澡人妻无码av蜜桃 | 精品无码一区二区三区爱欲 | 久久久久99精品成人片 | 人人澡人摸人人添 | 性生交片免费无码看人 | 欧美亚洲国产一区二区三区 | 九九在线中文字幕无码 | 好屌草这里只有精品 | 牲交欧美兽交欧美 | 亚洲中文字幕无码一久久区 | 亚洲中文字幕av在天堂 | 国产情侣作爱视频免费观看 | 国产精品久久久久久无码 | 国产小呦泬泬99精品 | 亚洲色www成人永久网址 | 自拍偷自拍亚洲精品10p | 午夜不卡av免费 一本久久a久久精品vr综合 | 欧美丰满少妇xxxx性 | 国产成人人人97超碰超爽8 | 亚洲一区二区三区国产精华液 | 欧美 丝袜 自拍 制服 另类 | 日本肉体xxxx裸交 | 成熟女人特级毛片www免费 | v一区无码内射国产 | 久久成人a毛片免费观看网站 | 久久www免费人成人片 | 激情亚洲一区国产精品 | 蜜桃av抽搐高潮一区二区 | 中文字幕av无码一区二区三区电影 | 亚洲精品一区国产 | 丝袜足控一区二区三区 | 午夜精品一区二区三区的区别 | 综合网日日天干夜夜久久 | 午夜福利试看120秒体验区 | 狠狠色欧美亚洲狠狠色www | 国产乱人伦偷精品视频 | 久久久久亚洲精品男人的天堂 | 国产成人一区二区三区在线观看 | 免费观看的无遮挡av | 一本久道久久综合婷婷五月 | 少妇愉情理伦片bd | 狂野欧美性猛xxxx乱大交 | 国产成人无码区免费内射一片色欲 | 中文无码精品a∨在线观看不卡 | 成 人影片 免费观看 | 精品国产乱码久久久久乱码 | 久久久www成人免费毛片 | 77777熟女视频在线观看 а天堂中文在线官网 | 免费无码一区二区三区蜜桃大 | 国产热a欧美热a在线视频 | 熟妇人妻无码xxx视频 | 精品亚洲成av人在线观看 | 99精品久久毛片a片 | 少妇愉情理伦片bd | 无码人妻久久一区二区三区不卡 | 人人妻人人澡人人爽人人精品 | 日日夜夜撸啊撸 | 久久天天躁夜夜躁狠狠 | 国产精品久免费的黄网站 | 成人亚洲精品久久久久 | 中文毛片无遮挡高清免费 | 免费播放一区二区三区 | 国产成人无码专区 | 日本免费一区二区三区最新 | 最近中文2019字幕第二页 | 少妇久久久久久人妻无码 | 国产免费观看黄av片 | 人妻插b视频一区二区三区 | 欧美兽交xxxx×视频 | 国产激情无码一区二区 | 欧美丰满熟妇xxxx性ppx人交 | 国产精品亚洲lv粉色 | 色综合久久网 | 久久久精品欧美一区二区免费 | 国产午夜视频在线观看 | 99er热精品视频 | 亚洲熟妇色xxxxx欧美老妇y | 日本护士xxxxhd少妇 | 俺去俺来也www色官网 | 日本熟妇大屁股人妻 | 大地资源网第二页免费观看 | 国产高清av在线播放 | 少妇高潮一区二区三区99 | 人妻少妇精品久久 | 少妇邻居内射在线 | 日韩精品a片一区二区三区妖精 | 中文字幕无码av波多野吉衣 | 欧美激情综合亚洲一二区 | 欧美国产日韩亚洲中文 | 男人的天堂2018无码 | 成人无码视频在线观看网站 | 青青青爽视频在线观看 | 7777奇米四色成人眼影 | 成年美女黄网站色大免费全看 | 国产精品久久久av久久久 | 99久久亚洲精品无码毛片 | 秋霞成人午夜鲁丝一区二区三区 | 性生交大片免费看女人按摩摩 | 国产一区二区三区精品视频 | 激情亚洲一区国产精品 | 国产乱子伦视频在线播放 | а√天堂www在线天堂小说 | 精品无码一区二区三区爱欲 | 精品国产国产综合精品 | 强奷人妻日本中文字幕 | 成年美女黄网站色大免费全看 | 中文字幕乱码亚洲无线三区 | 欧美xxxx黑人又粗又长 | 国产香蕉尹人综合在线观看 | 免费无码av一区二区 | 亚洲精品无码国产 | 国产精品内射视频免费 | 国产精品美女久久久久av爽李琼 | 在线 国产 欧美 亚洲 天堂 | 色欲人妻aaaaaaa无码 | 自拍偷自拍亚洲精品10p | 特级做a爰片毛片免费69 | 少妇无码av无码专区在线观看 | а√资源新版在线天堂 | 国语精品一区二区三区 | 女人和拘做爰正片视频 | 亚洲欧美国产精品久久 | 免费看男女做好爽好硬视频 | 亚洲欧洲无卡二区视頻 | 亚洲aⅴ无码成人网站国产app | 欧美日韩人成综合在线播放 | 人妻天天爽夜夜爽一区二区 | 国产区女主播在线观看 | 国产精品久久久一区二区三区 | 影音先锋中文字幕无码 | 国产成人无码区免费内射一片色欲 | 欧美freesex黑人又粗又大 | 在线观看国产午夜福利片 | a片在线免费观看 | 国产成人综合色在线观看网站 | 国产av人人夜夜澡人人爽麻豆 | 午夜无码区在线观看 | 俄罗斯老熟妇色xxxx | 国产黑色丝袜在线播放 | 熟妇人妻无码xxx视频 | 国产乱人偷精品人妻a片 | 国色天香社区在线视频 | 久久久精品456亚洲影院 | 九九综合va免费看 | 国产超级va在线观看视频 | 亚洲啪av永久无码精品放毛片 | 丰满人妻精品国产99aⅴ | 国产农村妇女高潮大叫 | 精品国产青草久久久久福利 | 免费无码av一区二区 | 亚洲第一无码av无码专区 | 亚洲码国产精品高潮在线 | 欧美喷潮久久久xxxxx | 久久99精品久久久久久 | 奇米影视888欧美在线观看 | 成人免费无码大片a毛片 | 免费无码一区二区三区蜜桃大 | 免费看男女做好爽好硬视频 | 国产精品自产拍在线观看 | 成人综合网亚洲伊人 | 中文字幕无码av波多野吉衣 | 免费无码午夜福利片69 | 日本一卡2卡3卡四卡精品网站 | 大乳丰满人妻中文字幕日本 | 日日鲁鲁鲁夜夜爽爽狠狠 | 亚洲精品无码人妻无码 | 51国偷自产一区二区三区 | 黑人大群体交免费视频 | 国产成人av免费观看 | 天天摸天天碰天天添 | 99久久人妻精品免费二区 | 7777奇米四色成人眼影 | 男女猛烈xx00免费视频试看 | 亚洲第一网站男人都懂 | 国产av无码专区亚洲awww | 午夜成人1000部免费视频 | 国产亚洲精品久久久久久久久动漫 | 性啪啪chinese东北女人 | 99久久精品午夜一区二区 | 久久aⅴ免费观看 | 少妇被粗大的猛进出69影院 | 亚洲色www成人永久网址 | 亚洲午夜无码久久 | 六月丁香婷婷色狠狠久久 | 欧美老妇与禽交 | 亚洲国产精品美女久久久久 | 无码人妻出轨黑人中文字幕 | 精品水蜜桃久久久久久久 | 人妻少妇精品无码专区二区 | 免费无码av一区二区 | 国产精品久久久久无码av色戒 | 欧洲极品少妇 | 青草青草久热国产精品 | 少妇性l交大片 | 妺妺窝人体色www婷婷 | 牲欲强的熟妇农村老妇女视频 | 暴力强奷在线播放无码 | 男女爱爱好爽视频免费看 | 无码播放一区二区三区 | 国产内射爽爽大片视频社区在线 | 老子影院午夜伦不卡 | 亚洲综合另类小说色区 | 免费播放一区二区三区 | 在线观看国产午夜福利片 | 蜜桃av抽搐高潮一区二区 | 久久久久久久女国产乱让韩 | 久久亚洲国产成人精品性色 | 自拍偷自拍亚洲精品被多人伦好爽 | 99久久精品国产一区二区蜜芽 | av无码电影一区二区三区 | 激情爆乳一区二区三区 | 亚洲欧洲日本综合aⅴ在线 | 国产熟妇高潮叫床视频播放 | 亚洲乱码国产乱码精品精 | 亚洲精品午夜国产va久久成人 | 性做久久久久久久免费看 | 麻豆国产人妻欲求不满 | 亚洲va欧美va天堂v国产综合 | 久久久亚洲欧洲日产国码αv | 国语自产偷拍精品视频偷 | 丝袜足控一区二区三区 | 亚洲 日韩 欧美 成人 在线观看 | 中文字幕无码乱人伦 | 全黄性性激高免费视频 | 无遮无挡爽爽免费视频 | 久久精品无码一区二区三区 | 欧美精品一区二区精品久久 | 日本在线高清不卡免费播放 | 国产免费久久精品国产传媒 | 欧美日韩一区二区综合 | 中文字幕无码av波多野吉衣 | 国内精品久久久久久中文字幕 | 久久无码人妻影院 | 成人免费视频一区二区 | 男女下面进入的视频免费午夜 | 三级4级全黄60分钟 | 久久 国产 尿 小便 嘘嘘 | 国产精品无码一区二区桃花视频 | а天堂中文在线官网 | 国产亚洲日韩欧美另类第八页 | 国产女主播喷水视频在线观看 | 国产精品永久免费视频 | 国产精品第一国产精品 | 亚洲熟熟妇xxxx | 日本护士毛茸茸高潮 | 三上悠亚人妻中文字幕在线 | 色综合久久久无码中文字幕 | 欧美性猛交内射兽交老熟妇 | 国产人妻久久精品二区三区老狼 | 国产精品福利视频导航 | 国产精品免费大片 | 老太婆性杂交欧美肥老太 | 国产成人无码午夜视频在线观看 | 久久无码专区国产精品s | av在线亚洲欧洲日产一区二区 | 亚拍精品一区二区三区探花 | 18黄暴禁片在线观看 | 亚洲国产精品无码久久久久高潮 | 国产精品无码一区二区桃花视频 | 国产精品.xx视频.xxtv | 中文字幕无线码免费人妻 | 欧美一区二区三区视频在线观看 | 欧美国产亚洲日韩在线二区 | 人妻尝试又大又粗久久 | 国内精品久久久久久中文字幕 | 亚洲国产精品无码久久久久高潮 | 精品国产成人一区二区三区 | 丰满少妇人妻久久久久久 | 久久久久成人精品免费播放动漫 | 亚洲码国产精品高潮在线 | 鲁大师影院在线观看 | 亚洲性无码av中文字幕 | 欧美精品国产综合久久 | 丰满少妇人妻久久久久久 | 久久久久亚洲精品中文字幕 | 少妇愉情理伦片bd | 无码人妻精品一区二区三区不卡 | 奇米影视7777久久精品 | 人人爽人人澡人人高潮 | 奇米影视888欧美在线观看 | 99久久99久久免费精品蜜桃 | 色综合久久中文娱乐网 | 伊在人天堂亚洲香蕉精品区 | 亚洲一区二区三区偷拍女厕 | 国产午夜精品一区二区三区嫩草 | 乱中年女人伦av三区 | 无码一区二区三区在线观看 | 蜜桃av抽搐高潮一区二区 | 小sao货水好多真紧h无码视频 | 久久精品国产一区二区三区肥胖 | 欧美熟妇另类久久久久久多毛 | 成人女人看片免费视频放人 | 蜜臀aⅴ国产精品久久久国产老师 | 成熟女人特级毛片www免费 | 午夜福利一区二区三区在线观看 | a国产一区二区免费入口 | 中文字幕无码日韩专区 | 亚洲伊人久久精品影院 | 国产成人精品视频ⅴa片软件竹菊 | 无码人妻精品一区二区三区下载 | 欧美人与物videos另类 | 欧美精品一区二区精品久久 | 久久久久免费看成人影片 | 国产真实夫妇视频 | 国产精品理论片在线观看 | 久久久久99精品成人片 | 日产国产精品亚洲系列 | 四十如虎的丰满熟妇啪啪 | 亚洲日韩乱码中文无码蜜桃臀网站 | 日本大香伊一区二区三区 | 无码成人精品区在线观看 | 波多野结衣乳巨码无在线观看 | 偷窥村妇洗澡毛毛多 | 一本久道久久综合狠狠爱 | 国产精品国产三级国产专播 | 国产偷国产偷精品高清尤物 | 女高中生第一次破苞av | 性欧美牲交xxxxx视频 | 亚洲日韩av一区二区三区四区 | 亚洲日韩av片在线观看 | 宝宝好涨水快流出来免费视频 | 天下第一社区视频www日本 | 国产精品内射视频免费 | 男女超爽视频免费播放 | 欧美熟妇另类久久久久久多毛 | 午夜福利不卡在线视频 | 亚洲欧美国产精品专区久久 | 少妇激情av一区二区 | 色婷婷欧美在线播放内射 | 国产精品无码一区二区桃花视频 | 久久99久久99精品中文字幕 | 国产精品久久久久无码av色戒 | 色一情一乱一伦 | 亚洲精品www久久久 | 国产人妻人伦精品1国产丝袜 | 国产午夜亚洲精品不卡下载 | 人妻体内射精一区二区三四 | 67194成是人免费无码 | 天下第一社区视频www日本 | 国产午夜福利亚洲第一 | 色情久久久av熟女人妻网站 | 欧美性生交xxxxx久久久 | 国产精品久久久久影院嫩草 | 国产一精品一av一免费 | 国产免费久久精品国产传媒 | 动漫av网站免费观看 | 欧美人与禽zoz0性伦交 | 丰满少妇高潮惨叫视频 | 亚洲精品国产品国语在线观看 | 全球成人中文在线 | 风流少妇按摩来高潮 | 亚洲国产一区二区三区在线观看 | 爱做久久久久久 | 无遮挡国产高潮视频免费观看 | 99国产欧美久久久精品 | 中文字幕无码免费久久99 | 国产成人无码a区在线观看视频app | 国产精品99久久精品爆乳 | 丰满人妻翻云覆雨呻吟视频 | 国产综合色产在线精品 | 夜夜躁日日躁狠狠久久av | 人妻中文无码久热丝袜 | 国产人妻久久精品二区三区老狼 | 精品无码国产自产拍在线观看蜜 | 成人亚洲精品久久久久软件 | 免费观看激色视频网站 | 亚洲 欧美 激情 小说 另类 | 东京热一精品无码av | 麻豆果冻传媒2021精品传媒一区下载 | 国产精品美女久久久网av | 精品无码一区二区三区爱欲 | 老头边吃奶边弄进去呻吟 | 大地资源中文第3页 | 99视频精品全部免费免费观看 | 爽爽影院免费观看 | 国产精品二区一区二区aⅴ污介绍 | 日韩无套无码精品 | 精品国产av色一区二区深夜久久 | 亚洲天堂2017无码 | 成人性做爰aaa片免费看 | 国产精品资源一区二区 | 中文字幕乱码亚洲无线三区 | 久久精品女人的天堂av | 国产精品第一国产精品 | 日本爽爽爽爽爽爽在线观看免 | www国产亚洲精品久久网站 | 成人亚洲精品久久久久软件 | 久久综合给合久久狠狠狠97色 | 国产激情无码一区二区app | 无码精品国产va在线观看dvd | 午夜精品一区二区三区的区别 | 日本丰满护士爆乳xxxx | 国产欧美熟妇另类久久久 | 国产综合久久久久鬼色 | 成年美女黄网站色大免费视频 | 久久久久久av无码免费看大片 | 国产综合色产在线精品 | 成人av无码一区二区三区 | 亚洲日本va午夜在线电影 | 欧美老妇交乱视频在线观看 | 色噜噜亚洲男人的天堂 | 无码国模国产在线观看 | 亚洲成av人影院在线观看 | 日日天干夜夜狠狠爱 | 国产色xx群视频射精 | 久久久久久亚洲精品a片成人 | 亚洲国产综合无码一区 | 国产人妻精品一区二区三区不卡 | 亚洲 日韩 欧美 成人 在线观看 | 久久综合香蕉国产蜜臀av | av小次郎收藏 | 国产内射爽爽大片视频社区在线 | 亚洲人成网站免费播放 | av无码不卡在线观看免费 | 婷婷色婷婷开心五月四房播播 | 日本又色又爽又黄的a片18禁 | 一本大道伊人av久久综合 | 5858s亚洲色大成网站www | 婷婷综合久久中文字幕蜜桃三电影 | 国产深夜福利视频在线 | 亚洲精品国产精品乱码视色 | 波多野42部无码喷潮在线 | 最近中文2019字幕第二页 | 人妻人人添人妻人人爱 | 自拍偷自拍亚洲精品被多人伦好爽 | 天下第一社区视频www日本 | 日日天干夜夜狠狠爱 | 爆乳一区二区三区无码 | 亚洲成av人片在线观看无码不卡 | 一本加勒比波多野结衣 | 99精品国产综合久久久久五月天 | 色一情一乱一伦一区二区三欧美 | 久久精品人人做人人综合 | 欧美 日韩 亚洲 在线 | 国产人妻精品一区二区三区不卡 | 丝袜 中出 制服 人妻 美腿 | 亚洲成熟女人毛毛耸耸多 | 日韩欧美中文字幕在线三区 | 中文字幕乱码人妻无码久久 | 色一情一乱一伦一区二区三欧美 | 亚洲爆乳精品无码一区二区三区 | 中文字幕无码免费久久99 | 国产精品二区一区二区aⅴ污介绍 | 久久久久成人精品免费播放动漫 | 熟妇人妻无乱码中文字幕 | 日韩无套无码精品 | 最近免费中文字幕中文高清百度 | 小sao货水好多真紧h无码视频 | 国产亚洲欧美在线专区 | 亚洲成av人影院在线观看 | 国产av无码专区亚洲awww | 影音先锋中文字幕无码 | 亚洲日本va午夜在线电影 | 国产精品99久久精品爆乳 | 欧美色就是色 | 国产农村妇女aaaaa视频 撕开奶罩揉吮奶头视频 | 老熟妇乱子伦牲交视频 | 青青青爽视频在线观看 | 99精品久久毛片a片 | 亚洲va中文字幕无码久久不卡 | 亚洲综合另类小说色区 | 国产在线精品一区二区高清不卡 | 欧美日韩亚洲国产精品 | 亚洲爆乳精品无码一区二区三区 | 99久久人妻精品免费二区 | 激情综合激情五月俺也去 | 久久久精品人妻久久影视 | 亚洲欧洲无卡二区视頻 | 人妻少妇精品无码专区二区 | 国产超级va在线观看视频 | 精品一区二区不卡无码av | 欧美丰满老熟妇xxxxx性 | 亚洲国产综合无码一区 | 强辱丰满人妻hd中文字幕 | 亚洲 另类 在线 欧美 制服 | 夜夜躁日日躁狠狠久久av | 亚洲国产欧美国产综合一区 | 欧美真人作爱免费视频 | 成人一在线视频日韩国产 | 一本加勒比波多野结衣 | 国产精品美女久久久网av | 青青青爽视频在线观看 | 亚洲欧美日韩综合久久久 | 国产精品99久久精品爆乳 | 国产三级久久久精品麻豆三级 | 天堂亚洲2017在线观看 | 精品久久久久香蕉网 | 国产手机在线αⅴ片无码观看 | 国产精品无码一区二区桃花视频 | 无码av最新清无码专区吞精 | 国产麻豆精品精东影业av网站 | 又黄又爽又色的视频 | 男女爱爱好爽视频免费看 | 99精品久久毛片a片 | 美女扒开屁股让男人桶 | 国产真人无遮挡作爱免费视频 | 午夜成人1000部免费视频 | 中文字幕无码人妻少妇免费 | 亚洲成av人影院在线观看 | 巨爆乳无码视频在线观看 | 国产精品永久免费视频 | 日本一区二区三区免费高清 | 激情国产av做激情国产爱 | 国产精品无码一区二区三区不卡 | 欧美放荡的少妇 | 少妇高潮一区二区三区99 | 精品久久久中文字幕人妻 | 成人无码精品一区二区三区 | 中文字幕无线码免费人妻 | 欧美日韩色另类综合 | 亚洲无人区一区二区三区 | 国产精品高潮呻吟av久久4虎 | 成人免费视频视频在线观看 免费 | 国产av人人夜夜澡人人爽麻豆 | 88国产精品欧美一区二区三区 | 国产三级久久久精品麻豆三级 | 日韩精品乱码av一区二区 | 东京一本一道一二三区 | 久久综合狠狠综合久久综合88 | 国产精品亚洲а∨无码播放麻豆 | 久久久久免费精品国产 | 色偷偷av老熟女 久久精品人妻少妇一区二区三区 | 欧美精品一区二区精品久久 | 1000部啪啪未满十八勿入下载 | 99久久99久久免费精品蜜桃 | 欧洲精品码一区二区三区免费看 | 欧洲熟妇色 欧美 | 成人性做爰aaa片免费看不忠 | 国产精品无码一区二区桃花视频 | 中文字幕乱码人妻无码久久 | av无码久久久久不卡免费网站 | 国产精品久久久久影院嫩草 | 蜜臀aⅴ国产精品久久久国产老师 | 亚洲精品一区二区三区在线 | 中文字幕色婷婷在线视频 | 蜜臀aⅴ国产精品久久久国产老师 | 国产极品美女高潮无套在线观看 | 亚洲人亚洲人成电影网站色 | 99riav国产精品视频 | 国产一区二区三区影院 | 国产精品亚洲五月天高清 | 无码精品人妻一区二区三区av | 亚洲中文字幕无码一久久区 | 国产精品久免费的黄网站 | 国产福利视频一区二区 | 日日碰狠狠丁香久燥 | 国产农村妇女高潮大叫 | 国内精品人妻无码久久久影院蜜桃 | 天天躁夜夜躁狠狠是什么心态 | 亚洲欧美日韩国产精品一区二区 | 成熟人妻av无码专区 | 亚洲综合精品香蕉久久网 | 人妻少妇被猛烈进入中文字幕 | 四虎影视成人永久免费观看视频 | 三级4级全黄60分钟 | 日本va欧美va欧美va精品 | 男人扒开女人内裤强吻桶进去 | 色一情一乱一伦一视频免费看 | 久久久久久国产精品无码下载 | 青青草原综合久久大伊人精品 | 在线看片无码永久免费视频 | 日韩av激情在线观看 | 久久久久久久人妻无码中文字幕爆 | 国产精品久久久久久亚洲影视内衣 | 国产午夜手机精彩视频 | 色老头在线一区二区三区 | 综合网日日天干夜夜久久 | 特级做a爰片毛片免费69 | 大色综合色综合网站 | 亚洲国产综合无码一区 | 国产在线aaa片一区二区99 | 色五月丁香五月综合五月 | 在线 国产 欧美 亚洲 天堂 | 欧美成人午夜精品久久久 | 亚洲а∨天堂久久精品2021 | 欧美日韩一区二区综合 | 在线看片无码永久免费视频 | 亚洲成av人片天堂网无码】 | 蜜桃臀无码内射一区二区三区 | 国产精品二区一区二区aⅴ污介绍 | 欧美真人作爱免费视频 | 一个人免费观看的www视频 | 日本熟妇人妻xxxxx人hd | 丝袜 中出 制服 人妻 美腿 | 图片小说视频一区二区 | 欧美丰满熟妇xxxx | 国产电影无码午夜在线播放 | 日韩欧美成人免费观看 | 97久久精品无码一区二区 | 久久亚洲日韩精品一区二区三区 | 亚洲精品欧美二区三区中文字幕 | 精品熟女少妇av免费观看 | 99久久精品午夜一区二区 | 99riav国产精品视频 | 欧美精品国产综合久久 | 2019午夜福利不卡片在线 | 成人亚洲精品久久久久 | 狠狠综合久久久久综合网 | 日日鲁鲁鲁夜夜爽爽狠狠 | 久久人人爽人人爽人人片av高清 | 99麻豆久久久国产精品免费 | a片免费视频在线观看 | 色一情一乱一伦 | 亚洲日韩av一区二区三区中文 | 内射后入在线观看一区 | 日本一区二区三区免费播放 | 久久亚洲精品中文字幕无男同 | 久久午夜无码鲁丝片秋霞 | 丁香花在线影院观看在线播放 | 久久久国产精品无码免费专区 | 九九久久精品国产免费看小说 | 少妇邻居内射在线 | 女人被爽到呻吟gif动态图视看 | 久久精品女人天堂av免费观看 | 国产在线一区二区三区四区五区 | 久久精品中文字幕一区 | 性欧美大战久久久久久久 | 少妇人妻av毛片在线看 | 国产av一区二区三区最新精品 | 超碰97人人射妻 | 中文字幕 人妻熟女 | 国产精品久久久久久亚洲影视内衣 | 未满小14洗澡无码视频网站 | 精品夜夜澡人妻无码av蜜桃 | 精品国产麻豆免费人成网站 | 日韩人妻无码一区二区三区久久99 | 欧美阿v高清资源不卡在线播放 | 欧美野外疯狂做受xxxx高潮 | 亚洲综合精品香蕉久久网 | 国产av人人夜夜澡人人爽麻豆 | 亚洲一区二区三区播放 | 亚洲国产午夜精品理论片 | 免费观看又污又黄的网站 | 麻豆人妻少妇精品无码专区 | 99久久久无码国产aaa精品 | 99久久久无码国产aaa精品 | 日本一卡2卡3卡4卡无卡免费网站 国产一区二区三区影院 | 亚洲国产午夜精品理论片 | 国产特级毛片aaaaaa高潮流水 | 在线 国产 欧美 亚洲 天堂 | 少女韩国电视剧在线观看完整 | 99精品无人区乱码1区2区3区 | 装睡被陌生人摸出水好爽 | 中文字幕日韩精品一区二区三区 | 国产两女互慰高潮视频在线观看 | 波多野结衣乳巨码无在线观看 | 清纯唯美经典一区二区 | 国产高清不卡无码视频 | 亚洲成a人一区二区三区 | 国产精品香蕉在线观看 | 国产精品亚洲专区无码不卡 | 亚洲精品鲁一鲁一区二区三区 | 成人免费视频在线观看 | 俺去俺来也在线www色官网 | 波多野42部无码喷潮在线 | 十八禁真人啪啪免费网站 | 久久久久久久女国产乱让韩 | 国产精品久久久午夜夜伦鲁鲁 | 国产女主播喷水视频在线观看 | 国产精品人妻一区二区三区四 | 日韩人妻少妇一区二区三区 | 无码人妻精品一区二区三区下载 | 欧美熟妇另类久久久久久多毛 | 少妇无码吹潮 | 国产午夜无码视频在线观看 | 性生交片免费无码看人 | 国产猛烈高潮尖叫视频免费 | 精品国产一区二区三区av 性色 | 欧美人与牲动交xxxx | 精品国产青草久久久久福利 | 国产熟妇高潮叫床视频播放 | 激情亚洲一区国产精品 | 免费无码av一区二区 | 欧美午夜特黄aaaaaa片 | 国产人妻人伦精品 | 久久熟妇人妻午夜寂寞影院 | 天天摸天天透天天添 | а√天堂www在线天堂小说 | 久久精品一区二区三区四区 | 久久久中文久久久无码 | 国产无套内射久久久国产 | 伊人久久婷婷五月综合97色 | 久久久久久亚洲精品a片成人 | 无套内射视频囯产 | 精品无人区无码乱码毛片国产 | 高潮喷水的毛片 | 国产精品久久福利网站 | 一本久道高清无码视频 | 欧美精品在线观看 | 亚洲最大成人网站 | 久久综合激激的五月天 | 亚洲精品国偷拍自产在线观看蜜桃 | 无码一区二区三区在线观看 | 又粗又大又硬毛片免费看 | 国产精品无码成人午夜电影 | 夜先锋av资源网站 | 国产亚洲精品久久久ai换 | 荫蒂添的好舒服视频囗交 | 天海翼激烈高潮到腰振不止 | 丁香啪啪综合成人亚洲 | 国产精品毛多多水多 | 又粗又大又硬毛片免费看 | 久久久国产一区二区三区 | 国产黄在线观看免费观看不卡 | 乱人伦人妻中文字幕无码久久网 | 国产欧美精品一区二区三区 | 欧美成人家庭影院 | 国产精品.xx视频.xxtv | 任你躁在线精品免费 | 大肉大捧一进一出好爽视频 | 亚洲色欲色欲欲www在线 | 日本大香伊一区二区三区 | 亚洲精品中文字幕乱码 | 国产精品多人p群无码 | 俺去俺来也在线www色官网 | 图片区 小说区 区 亚洲五月 | 欧美成人高清在线播放 | 人人妻人人澡人人爽人人精品浪潮 | 俺去俺来也在线www色官网 | 久久国产自偷自偷免费一区调 | 国产高潮视频在线观看 | 国产福利视频一区二区 | 国产精品久久久久久久影院 | 丰满肥臀大屁股熟妇激情视频 | 97精品国产97久久久久久免费 | 特黄特色大片免费播放器图片 | 久久人人爽人人爽人人片av高清 | 久久精品国产99久久6动漫 | 久久午夜无码鲁丝片 | 亚洲精品午夜无码电影网 | 国产精品永久免费视频 | 国产av久久久久精东av | 成熟妇人a片免费看网站 | 丰满妇女强制高潮18xxxx | 妺妺窝人体色www婷婷 | 国产精品第一国产精品 | 2019nv天堂香蕉在线观看 | 任你躁国产自任一区二区三区 | 成人性做爰aaa片免费看 | 国产成人无码专区 | 妺妺窝人体色www婷婷 | 国产人妻久久精品二区三区老狼 | 国产精品久久久久久亚洲影视内衣 | 成人无码视频在线观看网站 | 一区二区传媒有限公司 | 国产精品久久久一区二区三区 | 亚洲国产精品无码一区二区三区 | 鲁鲁鲁爽爽爽在线视频观看 | 少妇性俱乐部纵欲狂欢电影 | 国产超碰人人爽人人做人人添 | 天海翼激烈高潮到腰振不止 | 无码人妻黑人中文字幕 | 1000部夫妻午夜免费 | 亚洲国产精品毛片av不卡在线 | 亚洲高清偷拍一区二区三区 | 婷婷综合久久中文字幕蜜桃三电影 | 在线欧美精品一区二区三区 | 精品一区二区不卡无码av | 成人亚洲精品久久久久软件 | 日韩av无码一区二区三区不卡 | 嫩b人妻精品一区二区三区 | 久久精品国产99久久6动漫 | 少妇久久久久久人妻无码 | 婷婷六月久久综合丁香 | 巨爆乳无码视频在线观看 | 福利一区二区三区视频在线观看 | 色妞www精品免费视频 | 国产精品亚洲а∨无码播放麻豆 | 久久综合狠狠综合久久综合88 | 一个人看的www免费视频在线观看 | 色婷婷综合激情综在线播放 | 又色又爽又黄的美女裸体网站 | 毛片内射-百度 | 少妇一晚三次一区二区三区 | 国产精品永久免费视频 | 少妇性l交大片欧洲热妇乱xxx | 亚洲色偷偷男人的天堂 | 久久精品国产99精品亚洲 | 精品乱码久久久久久久 | 欧美日韩亚洲国产精品 | 精品aⅴ一区二区三区 | 精品水蜜桃久久久久久久 | 色偷偷av老熟女 久久精品人妻少妇一区二区三区 | 精品久久久久久亚洲精品 | 精品久久久久久人妻无码中文字幕 | аⅴ资源天堂资源库在线 | 国产亚洲人成在线播放 | 国产在线精品一区二区三区直播 | 纯爱无遮挡h肉动漫在线播放 | 夜夜高潮次次欢爽av女 | 国产疯狂伦交大片 | 色欲人妻aaaaaaa无码 | 三上悠亚人妻中文字幕在线 | 亚洲日本在线电影 | 中文字幕av无码一区二区三区电影 | 欧美精品一区二区精品久久 | 国产特级毛片aaaaaaa高清 | 欧美人与禽zoz0性伦交 | 日日鲁鲁鲁夜夜爽爽狠狠 | 四虎国产精品一区二区 | 亚洲一区二区三区在线观看网站 | 综合激情五月综合激情五月激情1 | 国产日产欧产精品精品app | 青青青爽视频在线观看 | 国产精品a成v人在线播放 | 成人免费无码大片a毛片 | 中文亚洲成a人片在线观看 | 又粗又大又硬又长又爽 | 女人被男人爽到呻吟的视频 | 亚洲一区二区三区四区 | 亚洲狠狠婷婷综合久久 | 国产97人人超碰caoprom | 亚拍精品一区二区三区探花 | av无码久久久久不卡免费网站 | 又粗又大又硬毛片免费看 | 天堂亚洲2017在线观看 | 亚洲国产精品无码一区二区三区 | 精品久久久久久人妻无码中文字幕 | 国产精品亚洲lv粉色 | 欧美成人午夜精品久久久 | 欧美人与物videos另类 | 少妇无套内谢久久久久 | 99re在线播放 | 夜先锋av资源网站 | 亚洲国产精品久久久天堂 | 成年美女黄网站色大免费视频 | 国产在线无码精品电影网 | 日韩精品a片一区二区三区妖精 | 伊在人天堂亚洲香蕉精品区 | 国产两女互慰高潮视频在线观看 | 女人被爽到呻吟gif动态图视看 | 天天躁夜夜躁狠狠是什么心态 | 国产莉萝无码av在线播放 | 中文字幕无码日韩专区 | 日本一卡二卡不卡视频查询 | 麻豆蜜桃av蜜臀av色欲av | 日韩在线不卡免费视频一区 | 亚洲成av人片在线观看无码不卡 | 国内精品久久毛片一区二区 | 国产精品毛片一区二区 | 亚洲精品国产品国语在线观看 | 日本丰满护士爆乳xxxx | 亚洲欧美日韩国产精品一区二区 | 麻豆av传媒蜜桃天美传媒 | 国产乱人伦av在线无码 | 国产精品久久久久久亚洲影视内衣 | 国产精品亚洲综合色区韩国 | 波多野结衣av一区二区全免费观看 | 亚洲综合精品香蕉久久网 | 未满小14洗澡无码视频网站 | 国产麻豆精品精东影业av网站 | 国产在线精品一区二区三区直播 | 精品一区二区三区无码免费视频 | 欧美国产日产一区二区 | 国产极品美女高潮无套在线观看 | 狠狠色噜噜狠狠狠狠7777米奇 | 中文字幕乱码人妻二区三区 | 中文字幕av伊人av无码av | 成人免费视频一区二区 | 在线观看免费人成视频 | 婷婷六月久久综合丁香 | 国产精品久久久久久久9999 | 精品无码一区二区三区爱欲 | 欧美 亚洲 国产 另类 | 久久精品人人做人人综合试看 | 一本无码人妻在中文字幕免费 | 久久久久免费看成人影片 | 久久久久成人精品免费播放动漫 | 亚洲日本va午夜在线电影 | 人人妻人人澡人人爽欧美一区九九 | 老司机亚洲精品影院 | 国产激情无码一区二区app | 露脸叫床粗话东北少妇 | 国产精品va在线观看无码 | 娇妻被黑人粗大高潮白浆 | 在线观看免费人成视频 | 精品人人妻人人澡人人爽人人 | 亚洲色欲久久久综合网东京热 | 欧美日韩综合一区二区三区 | 丰满护士巨好爽好大乳 | 亚洲一区二区三区含羞草 | 香港三级日本三级妇三级 | 性生交片免费无码看人 | 色婷婷综合中文久久一本 | 国产色视频一区二区三区 | 成人欧美一区二区三区黑人免费 | 亚洲人成无码网www | 午夜福利一区二区三区在线观看 | 最新国产麻豆aⅴ精品无码 | 日本高清一区免费中文视频 | 日本www一道久久久免费榴莲 | 一区二区三区高清视频一 | 青草青草久热国产精品 | 午夜无码人妻av大片色欲 | 熟妇人妻中文av无码 | 少妇无码吹潮 | 熟女少妇在线视频播放 | 午夜丰满少妇性开放视频 | 丰满人妻精品国产99aⅴ | 久久国语露脸国产精品电影 | 成人精品视频一区二区三区尤物 | 在线 国产 欧美 亚洲 天堂 | 好屌草这里只有精品 | 又黄又爽又色的视频 | 男女超爽视频免费播放 | 天天躁日日躁狠狠躁免费麻豆 | 国精产品一品二品国精品69xx | 六月丁香婷婷色狠狠久久 | 中文字幕 人妻熟女 | 人妻无码αv中文字幕久久琪琪布 | 丝袜人妻一区二区三区 | 久久精品国产精品国产精品污 | 久久久久免费精品国产 | 久久久www成人免费毛片 | 久久久久人妻一区精品色欧美 | 久久久久久av无码免费看大片 | 午夜福利试看120秒体验区 | 全黄性性激高免费视频 | 国产绳艺sm调教室论坛 | 国产亚洲精品久久久久久国模美 | 欧美日本精品一区二区三区 | 中文字幕乱码人妻无码久久 | 一本色道久久综合亚洲精品不卡 | 人妻中文无码久热丝袜 | 国内精品人妻无码久久久影院 | 精品久久久无码中文字幕 | 男女爱爱好爽视频免费看 | 无码av最新清无码专区吞精 | 日本成熟视频免费视频 | av人摸人人人澡人人超碰下载 | 精品国产一区二区三区四区 | 国产福利视频一区二区 | 亚洲精品国产a久久久久久 | 成人综合网亚洲伊人 | 97人妻精品一区二区三区 | 久久亚洲中文字幕精品一区 | 午夜成人1000部免费视频 | 高潮毛片无遮挡高清免费视频 | 欧美第一黄网免费网站 | 国产精品国产自线拍免费软件 | 永久黄网站色视频免费直播 | 97夜夜澡人人双人人人喊 | 久久久中文久久久无码 | 少妇久久久久久人妻无码 | 亚洲国产成人av在线观看 | 亚洲中文字幕av在天堂 | 无码人妻黑人中文字幕 | 国产精品久久久 | 丁香啪啪综合成人亚洲 | √天堂中文官网8在线 | 国产麻豆精品一区二区三区v视界 | 中文字幕无码人妻少妇免费 | 亚洲精品国产精品乱码视色 | 国产一区二区三区日韩精品 | 99久久人妻精品免费一区 | 日本护士毛茸茸高潮 | 自拍偷自拍亚洲精品被多人伦好爽 | 正在播放老肥熟妇露脸 | 狠狠综合久久久久综合网 | 国产av剧情md精品麻豆 | 人妻互换免费中文字幕 | 亚洲日韩av片在线观看 | 亚洲色欲色欲欲www在线 | 成人影院yy111111在线观看 | 久久国产精品偷任你爽任你 | 男女性色大片免费网站 | 亚洲精品美女久久久久久久 | 天堂在线观看www | 无遮无挡爽爽免费视频 | 天堂无码人妻精品一区二区三区 | 国产午夜福利100集发布 | 国产成人无码av片在线观看不卡 |