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

Go官方設(shè)計(jì)了一個(gè)信號(hào)量庫(kù)

開(kāi)發(fā) 后端
信號(hào)量(Semaphore),有時(shí)被稱為信號(hào)燈,是[多線程環(huán)境下使用的一種設(shè)施,是可以用來(lái)保證兩個(gè)或多個(gè)關(guān)鍵代碼段不被并發(fā)調(diào)用。在進(jìn)入一個(gè)關(guān)鍵代碼段之前,線程必須獲取一個(gè)信號(hào)量;一旦該關(guān)鍵代碼段完成了,那么該線程必須釋放信號(hào)量。

[[420244]]

前言

哈嘍,大家好,我是asong。在寫(xiě)上一篇文章請(qǐng)勿濫用goroutine時(shí),發(fā)現(xiàn)Go語(yǔ)言擴(kuò)展包提供了一個(gè)帶權(quán)重的信號(hào)量庫(kù)Semaphore,使用信號(hào)量我們可以實(shí)現(xiàn)一個(gè)"工作池"控制一定數(shù)量的goroutine并發(fā)工作。因?yàn)閷?duì)源碼抱有好奇的態(tài)度,所以在周末仔細(xì)看了一下這個(gè)庫(kù)并進(jìn)行了解析,在這里記錄一下。

何為信號(hào)量

要想知道一個(gè)東西是什么,我都愛(ài)去百度百科上搜一搜,輸入"信號(hào)量",這答案不就來(lái)了。

百度百科解釋:

信號(hào)量(Semaphore),有時(shí)被稱為信號(hào)燈,是[多線程環(huán)境下使用的一種設(shè)施,是可以用來(lái)保證兩個(gè)或多個(gè)關(guān)鍵代碼段不被并發(fā)調(diào)用。在進(jìn)入一個(gè)關(guān)鍵代碼段之前,線程必須獲取一個(gè)信號(hào)量;一旦該關(guān)鍵代碼段完成了,那么該線程必須釋放信號(hào)量。其它想進(jìn)入該關(guān)鍵代碼段的線程必須等待直到第一個(gè)線程釋放信號(hào)量。為了完成這個(gè)過(guò)程,需要?jiǎng)?chuàng)建一個(gè)信號(hào)量VI,然后將Acquire Semaphore VI以及Release Semaphore VI分別放置在每個(gè)關(guān)鍵代碼段的首末端。確認(rèn)這些信號(hào)量VI引用的是初始創(chuàng)建的信號(hào)量。

通過(guò)這段解釋我們可以得知什么是信號(hào)量,其實(shí)信號(hào)量就是一種變量或者抽象數(shù)據(jù)類型,用于控制并發(fā)系統(tǒng)中多個(gè)進(jìn)程對(duì)公共資源的訪問(wèn),訪問(wèn)具有原子性。信號(hào)量主要分為兩類:

  • 二值信號(hào)量:顧名思義,其值只有兩種0或者1,相當(dāng)于互斥量,當(dāng)值為1時(shí)資源可用,當(dāng)值為0時(shí),資源被鎖住,進(jìn)程阻塞無(wú)法繼續(xù)執(zhí)行。
  • 計(jì)數(shù)信號(hào)量:信號(hào)量是一個(gè)任意的整數(shù),起始時(shí),如果計(jì)數(shù)器的計(jì)數(shù)值為0,那么創(chuàng)建出來(lái)的信號(hào)量就是不可獲得的狀態(tài),如果計(jì)數(shù)器的計(jì)數(shù)值大于0,那么創(chuàng)建出來(lái)的信號(hào)量就是可獲得的狀態(tài),并且總共獲取的次數(shù)等于計(jì)數(shù)器的值。

信號(hào)量工作原理

信號(hào)量是由操作系統(tǒng)來(lái)維護(hù)的,信號(hào)量只能進(jìn)行兩種操作等待和發(fā)送信號(hào),操作總結(jié)來(lái)說(shuō),核心就是PV操作:

  • P原語(yǔ):P是荷蘭語(yǔ)Proberen(測(cè)試)的首字母。為阻塞原語(yǔ),負(fù)責(zé)把當(dāng)前進(jìn)程由運(yùn)行狀態(tài)轉(zhuǎn)換為阻塞狀態(tài),直到另外一個(gè)進(jìn)程喚醒它。操作為:申請(qǐng)一個(gè)空閑資源(把信號(hào)量減1),若成功,則退出;若失敗,則該進(jìn)程被阻塞;
  • V原語(yǔ):V是荷蘭語(yǔ)Verhogen(增加)的首字母。為喚醒原語(yǔ),負(fù)責(zé)把一個(gè)被阻塞的進(jìn)程喚醒,它有一個(gè)參數(shù)表,存放著等待被喚醒的進(jìn)程信息。操作為:釋放一個(gè)被占用的資源(把信號(hào)量加1),如果發(fā)現(xiàn)有被阻塞的進(jìn)程,則選擇一個(gè)喚醒之。

在信號(hào)量進(jìn)行PV操作時(shí)都為原子操作,并且在PV原語(yǔ)執(zhí)行期間不允許有中斷的發(fā)生。

PV原語(yǔ)對(duì)信號(hào)量的操作可以分為三種情況:

  • 把信號(hào)量視為某種類型的共享資源的剩余個(gè)數(shù),實(shí)現(xiàn)對(duì)一類共享資源的訪問(wèn)
  • 把信號(hào)量用作進(jìn)程間的同步
  • 視信號(hào)量為一個(gè)加鎖標(biāo)志,實(shí)現(xiàn)對(duì)一個(gè)共享變量的訪問(wèn)

具體在什么場(chǎng)景使用本文就不在繼續(xù)分析,接下來(lái)我們重點(diǎn)來(lái)看一下Go語(yǔ)言提供的擴(kuò)展包Semaphore,看看它是怎樣實(shí)現(xiàn)的。

官方擴(kuò)展包Semaphore

我們之前在分析Go語(yǔ)言源碼時(shí)總會(huì)看到這幾個(gè)函數(shù):

  1. func runtime_Semacquire(s *uint32) 
  2. func runtime_SemacquireMutex(s *uint32, lifo bool, skipframes int
  3. func runtime_Semrelease(s *uint32, handoff bool, skipframes int

這幾個(gè)函數(shù)就是信號(hào)量的PV操作,不過(guò)他們都是給Go內(nèi)部使用的,如果想使用信號(hào)量,那就可以使用官方的擴(kuò)展包:Semaphore,這是一個(gè)帶權(quán)重的信號(hào)量,接下來(lái)我們就重點(diǎn)分析一下這個(gè)庫(kù)。

安裝方法:go get -u golang.org/x/sync

數(shù)據(jù)結(jié)構(gòu)

  1. type Weighted struct { 
  2.  size    int64 // 設(shè)置一個(gè)最大權(quán)值 
  3.  cur     int64 // 標(biāo)識(shí)當(dāng)前已被使用的資源數(shù) 
  4.  mu      sync.Mutex // 提供臨界區(qū)保護(hù) 
  5.  waiters list.List // 阻塞等待的調(diào)用者列表 

semaphore庫(kù)核心結(jié)構(gòu)就是Weighted,主要有4個(gè)字段:

  • size:這個(gè)代表的是最大權(quán)值,在創(chuàng)建Weighted對(duì)象指定
  • cur:相當(dāng)于一個(gè)游標(biāo),來(lái)記錄當(dāng)前已使用的權(quán)值
  • mu:互斥鎖,并發(fā)情況下做臨界區(qū)保護(hù)
  • waiters:阻塞等待的調(diào)用者列表,使用鏈表數(shù)據(jù)結(jié)構(gòu)保證先進(jìn)先出的順序,存儲(chǔ)的數(shù)據(jù)是waiter對(duì)象,waiter數(shù)據(jù)結(jié)構(gòu)如下:
  1. type waiter struct { 
  2.  n     int64 // 等待調(diào)用者權(quán)重值 
  3.  ready chan<- struct{} // close channel就是喚醒 

這里只有兩個(gè)字段:

  • n:這個(gè)就是等待調(diào)用者的權(quán)重值
  • ready:這就是一個(gè)channel,利用channel的close機(jī)制實(shí)現(xiàn)喚醒

semaphore還提供了一個(gè)創(chuàng)建Weighted對(duì)象的方法,在初始化時(shí)需要給定最大權(quán)值:

  1. // NewWeighted為并發(fā)訪問(wèn)創(chuàng)建一個(gè)新的加權(quán)信號(hào)量,該信號(hào)量具有給定的最大權(quán)值。 
  2. func NewWeighted(n int64) *Weighted { 
  3.  w := &Weighted{size: n} 
  4.  return w 

阻塞獲取權(quán)值的方法 - Acquire

先直接看代碼吧:

  1. func (s *Weighted) Acquire(ctx context.Context, n int64) error { 
  2.  s.mu.Lock() // 加鎖保護(hù)臨界區(qū) 
  3.  // 有資源可用并且沒(méi)有等待獲取權(quán)值的goroutine 
  4.  if s.size-s.cur >= n && s.waiters.Len() == 0 { 
  5.   s.cur += n // 加權(quán) 
  6.   s.mu.Unlock() // 釋放鎖 
  7.   return nil 
  8.  } 
  9.  // 要獲取的權(quán)值n大于最大的權(quán)值了 
  10.  if n > s.size { 
  11.   // 先釋放鎖,確保其他goroutine調(diào)用Acquire的地方不被阻塞 
  12.   s.mu.Unlock() 
  13.   // 阻塞等待context的返回 
  14.   <-ctx.Done() 
  15.   return ctx.Err() 
  16.  } 
  17.  // 走到這里就說(shuō)明現(xiàn)在沒(méi)有資源可用了 
  18.  // 創(chuàng)建一個(gè)channel用來(lái)做通知喚醒 
  19.  ready := make(chan struct{}) 
  20.  // 創(chuàng)建waiter對(duì)象 
  21.  w := waiter{n: n, ready: ready} 
  22.  // waiter按順序入隊(duì) 
  23.  elem := s.waiters.PushBack(w) 
  24.  // 釋放鎖,等待喚醒,別阻塞其他goroutine 
  25.  s.mu.Unlock() 
  26.  
  27.  // 阻塞等待喚醒 
  28.  select { 
  29.  // context關(guān)閉 
  30.  case <-ctx.Done(): 
  31.   err := ctx.Err() // 先獲取context的錯(cuò)誤信息 
  32.   s.mu.Lock() 
  33.   select { 
  34.   case <-ready: 
  35.    // 在context被關(guān)閉后被喚醒了,那么試圖修復(fù)隊(duì)列,假裝我們沒(méi)有取消 
  36.    err = nil 
  37.   default
  38.    // 判斷是否是第一個(gè)元素 
  39.    isFront := s.waiters.Front() == elem 
  40.    // 移除第一個(gè)元素 
  41.    s.waiters.Remove(elem) 
  42.    // 如果是第一個(gè)元素且有資源可用通知其他waiter 
  43.    if isFront && s.size > s.cur { 
  44.     s.notifyWaiters() 
  45.    } 
  46.   } 
  47.   s.mu.Unlock() 
  48.   return err 
  49.  // 被喚醒了 
  50.  case <-ready: 
  51.   return nil 
  52.  } 

注釋已經(jīng)加到代碼中了,總結(jié)一下這個(gè)方法主要有三個(gè)流程:

  • 流程一:有資源可用時(shí)并且沒(méi)有等待權(quán)值的goroutine,走正常加權(quán)流程;
  • 流程二:想要獲取的權(quán)值n大于初始化時(shí)設(shè)置最大的權(quán)值了,這個(gè)goroutine永遠(yuǎn)不會(huì)獲取到信號(hào)量,所以阻塞等待context的關(guān)閉;
  • 流程三:前兩步都沒(méi)問(wèn)題的話,就說(shuō)明現(xiàn)在系統(tǒng)沒(méi)有資源可用了,這時(shí)就需要阻塞等待喚醒,在阻塞等待喚醒這里有特殊邏輯;
    • 特殊邏輯二:context關(guān)閉后,則根據(jù)是否有可用資源決定通知后面等待喚醒的調(diào)用者,這樣做的目的其實(shí)是為了避免當(dāng)不同的context控制不同的goroutine時(shí),未關(guān)閉的goroutine不會(huì)被阻塞住,依然執(zhí)行,來(lái)看這樣一個(gè)例子(因?yàn)間oroutine的搶占式調(diào)度,所以這個(gè)例子也會(huì)具有偶然性):
    • 特殊邏輯一:如果在context被關(guān)閉后被喚醒了,那么就先忽略掉這個(gè)cancel,試圖修復(fù)隊(duì)列。
  1. func main()  { 
  2.  s := semaphore.NewWeighted(3) 
  3.  ctx,cancel := context.WithTimeout(context.Background(), time.Second * 2) 
  4.  defer cancel() 
  5.  
  6.  for i :=0; i < 3; i++{ 
  7.    if i != 0{ 
  8.     go func(num int) { 
  9.      if err := s.Acquire(ctx,3); err != nil{ 
  10.       fmt.Printf("goroutine: %d, err is %s\n", num, err.Error()) 
  11.       return 
  12.      } 
  13.      time.Sleep(2 * time.Second
  14.      fmt.Printf("goroutine: %d run over\n",num) 
  15.      s.Release(3) 
  16.  
  17.     }(i) 
  18.    }else { 
  19.     go func(num int) { 
  20.      ct,cancel := context.WithTimeout(context.Background(), time.Second * 3) 
  21.      defer cancel() 
  22.      if err := s.Acquire(ct,3); err != nil{ 
  23.       fmt.Printf("goroutine: %d, err is %s\n", num, err.Error()) 
  24.       return 
  25.      } 
  26.      time.Sleep(3 * time.Second
  27.      fmt.Printf("goroutine: %d run over\n",num) 
  28.      s.Release(3) 
  29.     }(i) 
  30.    } 
  31.  
  32.  } 
  33.  time.Sleep(10 * time.Second

上面的例子中g(shù)oroutine:0 使用ct對(duì)象來(lái)做控制,超時(shí)時(shí)間為3s,goroutine:1和goroutine:2對(duì)象使用ctx對(duì)象來(lái)做控制,超時(shí)時(shí)間為2s,這三個(gè)goroutine占用的資源都等于最大資源數(shù),也就是說(shuō)只能有一個(gè)goruotine運(yùn)行成功,另外兩個(gè)goroutine都會(huì)被阻塞,因?yàn)間oroutine是搶占式調(diào)度,所以我們不能確定哪個(gè)gouroutine會(huì)第一個(gè)被執(zhí)行,這里我們假設(shè)第一個(gè)獲取到信號(hào)量的是gouroutine:2,阻塞等待的調(diào)用者列表順序是:goroutine:1 -> goroutine:0,因?yàn)樵趃oroutine:2中有一個(gè)2s的延時(shí),所以會(huì)觸發(fā)ctx的超時(shí),ctx會(huì)下發(fā)Done信號(hào),因?yàn)間oroutine:2和goroutine:1都是被ctx控制的,所以就會(huì)把goroutine:1從等待者隊(duì)列中取消,但是因?yàn)間oroutine:1屬于隊(duì)列的第一個(gè)隊(duì)員,并且因?yàn)間oroutine:2已經(jīng)釋放資源,那么就會(huì)喚醒goroutine:0繼續(xù)執(zhí)行,畫(huà)個(gè)圖表示一下:

使用這種方式可以避免goroutine永久失眠。

不阻塞獲取權(quán)值的方法 - TryAcquire

  1. func (s *Weighted) TryAcquire(n int64) bool { 
  2.  s.mu.Lock() // 加鎖 
  3.  // 有資源可用并且沒(méi)有等待獲取資源的goroutine 
  4.  success := s.size-s.cur >= n && s.waiters.Len() == 0 
  5.  if success { 
  6.   s.cur += n 
  7.  } 
  8.  s.mu.Unlock() 
  9.  return success 

這個(gè)方法就簡(jiǎn)單很多了,不阻塞地獲取權(quán)重為n的信號(hào)量,成功時(shí)返回true,失敗時(shí)返回false并保持信號(hào)量不變。

釋放權(quán)重

  1. func (s *Weighted) Release(n int64) { 
  2.  s.mu.Lock() 
  3.  // 釋放資源 
  4.  s.cur -= n 
  5.  // 釋放資源大于持有的資源,則會(huì)發(fā)生panic 
  6.  if s.cur < 0 { 
  7.   s.mu.Unlock() 
  8.   panic("semaphore: released more than held"
  9.  } 
  10.  // 通知其他等待的調(diào)用者 
  11.  s.notifyWaiters() 
  12.  s.mu.Unlock() 

這里就是很常規(guī)的操作,主要就是資源釋放,同時(shí)進(jìn)行安全性判斷,如果釋放資源大于持有的資源,則會(huì)發(fā)生panic。

喚醒waiter

在Acquire和Release方法中都調(diào)用了notifyWaiters,我們來(lái)分析一下這個(gè)方法:

  1. func (s *Weighted) notifyWaiters() { 
  2.  for { 
  3.   // 獲取等待調(diào)用者隊(duì)列中的隊(duì)員 
  4.   next := s.waiters.Front() 
  5.   // 沒(méi)有要通知的調(diào)用者了 
  6.   if next == nil { 
  7.    break // No more waiters blocked. 
  8.   } 
  9.  
  10.   // 斷言出waiter信息 
  11.   w := next.Value.(waiter) 
  12.   if s.size-s.cur < w.n { 
  13.    // 沒(méi)有足夠資源為下一個(gè)調(diào)用者使用時(shí),繼續(xù)阻塞該調(diào)用者,遵循先進(jìn)先出的原則, 
  14.    // 避免需要資源數(shù)比較大的waiter被餓死 
  15.    // 
  16.    // 考慮一個(gè)場(chǎng)景,使用信號(hào)量作為讀寫(xiě)鎖,現(xiàn)有N個(gè)令牌,N個(gè)reader和一個(gè)writer 
  17.    // 每個(gè)reader都可以通過(guò)Acquire(1)獲取讀鎖,writer寫(xiě)入可以通過(guò)Acquire(N)獲得寫(xiě)鎖定 
  18.    // 但不包括所有的reader,如果我們?cè)试Sreader在隊(duì)列中前進(jìn),writer將會(huì)餓死-總是有一個(gè)令牌可供每個(gè)reader 
  19.    break 
  20.   } 
  21.  
  22.   // 獲取資源 
  23.   s.cur += w.n 
  24.   // 從waiter列表中移除 
  25.   s.waiters.Remove(next
  26.   // 使用channel的close機(jī)制喚醒waiter 
  27.   close(w.ready) 
  28.  } 

這里只需要注意一個(gè)點(diǎn):?jiǎn)拘褀aiter采用先進(jìn)先出的原則,避免需要資源數(shù)比較大的waiter被餓死。

何時(shí)使用Semaphore

到這里我們就把Semaphore的源代碼看了一篇,代碼行數(shù)不多,封裝的也很巧妙,那么我們?cè)撌裁磿r(shí)候選擇使用它呢?

目前能想到一個(gè)場(chǎng)景就是Semaphore配合上errgroup實(shí)現(xiàn)一個(gè)"工作池",使用Semaphore限制goroutine的數(shù)量,配合上errgroup做并發(fā)控制,示例如下:

  1. const ( 
  2.  limit = 2 
  3. )  
  4.  
  5. func main()  { 
  6.  serviceName := []string{ 
  7.   "cart"
  8.   "order"
  9.   "account"
  10.   "item"
  11.   "menu"
  12.  } 
  13.  eg,ctx := errgroup.WithContext(context.Background()) 
  14.  s := semaphore.NewWeighted(limit) 
  15.  for index := range serviceName{ 
  16.   name := serviceName[index
  17.   if err := s.Acquire(ctx,1); err != nil{ 
  18.    fmt.Printf("Acquire failed and err is %s\n", err.Error()) 
  19.    break 
  20.   } 
  21.   eg.Go(func() error { 
  22.    defer s.Release(1) 
  23.    return callService(name
  24.   }) 
  25.  } 
  26.  
  27.  if err := eg.Wait(); err != nil{ 
  28.   fmt.Printf("err is %s\n", err.Error()) 
  29.   return 
  30.  } 
  31.  fmt.Printf("run success\n"
  32.  
  33. func callService(name string) error { 
  34.  fmt.Println("call ",name
  35.  time.Sleep(1 * time.Second
  36.  return nil 

結(jié)果如下:

  1. call  order 
  2. call  cart 
  3. call  account 
  4. call  item 
  5. call  menu 
  6. run success 

總結(jié)

本文我們主要賞析了Go官方擴(kuò)展庫(kù)Semaphore的實(shí)現(xiàn),他的設(shè)計(jì)思路簡(jiǎn)單,僅僅用幾十行就完成了完美的封裝,值得我們借鑒學(xué)習(xí)。不過(guò)在實(shí)際業(yè)務(wù)場(chǎng)景中,我們使用信號(hào)量的場(chǎng)景并不多,大多數(shù)場(chǎng)景我們都可以使用channel來(lái)替代,但是有些場(chǎng)景使用Semaphore來(lái)實(shí)現(xiàn)會(huì)更好,比如上篇文章【[警惕] 請(qǐng)勿濫用goroutine】我們使用channel+sync來(lái)控制goroutine數(shù)量,這種實(shí)現(xiàn)方式并不好,因?yàn)閷?shí)際已經(jīng)起來(lái)了多個(gè)goroutine,只不過(guò)控制了工作的goroutine數(shù)量,如果改用semaphore實(shí)現(xiàn)才是真正的控制了goroutine數(shù)量。

 

文中代碼已上傳github:https://github.com/asong2020/Golang_Dream/blob/master/code_demo/semaphore_demo/semaphore.go,歡迎star。

 

責(zé)任編輯:武曉燕 來(lái)源: Golang夢(mèng)工廠
相關(guān)推薦

2023-08-28 07:04:17

2021-04-13 09:20:15

鴻蒙HarmonyOS應(yīng)用開(kāi)發(fā)

2020-11-05 09:59:24

Linux內(nèi)核信號(hào)量

2010-04-21 16:50:31

Unix信號(hào)量

2021-09-07 07:53:42

Semaphore 信號(hào)量源碼

2010-04-21 16:25:13

Unix信號(hào)量

2010-04-21 16:42:48

Unix信號(hào)量

2010-04-21 15:37:38

Unix信號(hào)量

2020-09-25 07:34:40

Linux系統(tǒng)編程信號(hào)量

2021-04-30 00:00:50

Semaphore信號(hào)量面試官

2024-10-29 15:23:45

Python線程安全

2019-11-19 09:00:38

JavaAND信號(hào)量

2010-03-17 16:36:10

Java信號(hào)量模型

2010-04-21 17:10:25

Unix信號(hào)量

2009-12-08 12:14:43

2010-07-15 15:32:10

Perl線程

2016-11-23 16:08:24

Python處理器分布式系統(tǒng)

2010-03-16 17:52:27

Java多線程信號(hào)量

2017-05-11 14:05:25

Consul分布式信號(hào)量

2021-02-03 20:10:29

Linux信號(hào)量shell
點(diǎn)贊
收藏

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

欧美精品 日韩| 国产精品妹子av| 欧美综合第一页| 男女男精品视频网站| 国产精品一区二区美女视频免费看| 亚洲美女免费在线| 裸模一区二区三区免费| 91麻豆国产在线| 亚洲经典在线看| 国产一区二区黄| 97超碰免费在线观看| 成人影院大全| 亚洲精品高清在线观看| 欧美一区二视频在线免费观看| 亚洲熟女乱色一区二区三区久久久| 国内精品久久久久久久影视蜜臀 | 国产一区二区三区天码| 这里只有精品视频在线观看| 国产成人在线免费看| 成人在线免费看黄| 久久久久久久久一| 99久久无色码| 亚洲影视一区二区| 久久99伊人| 久久久久免费视频| 美女视频久久久| 国产免费播放一区二区| 精品成人免费观看| 激情在线观看视频| yy6080久久伦理一区二区| 亚洲1区2区3区4区| 天堂а√在线中文在线 | 色妞久久福利网| 青青草视频成人| 老牛影视av一区二区在线观看| 91精品欧美久久久久久动漫| 天堂一区在线观看| 成人免费福利| 色综合久久久久综合体| 99在线精品免费视频| 欧洲在线视频| 亚洲精品免费在线| 大桥未久一区二区| 国产在线高潮| 亚洲精品乱码久久久久久| 中文字幕av日韩精品| 岛国在线视频| 国产欧美1区2区3区| 日韩电影免费观看在| 欧美色18zzzzxxxxx| 99久久99久久精品国产片果冻 | 中文字幕人成不卡一区| 亚洲人成网站在线播放2019| 成黄免费在线| 中文一区二区完整视频在线观看| 免费99视频| 美州a亚洲一视本频v色道| 2欧美一区二区三区在线观看视频| 成人黄色在线免费观看| 国产aⅴ一区二区三区| 国产资源精品在线观看| 91久久久久久久一区二区 | 亚洲第一页中文字幕| 熟女人妻一区二区三区免费看| 亚洲三级av| 亚洲成人av在线播放| 男人网站在线观看| 日韩激情毛片| 国产亚洲欧美日韩美女| 黑人と日本人の交わりビデオ| 91视频综合| 欧美成人手机在线| 国产在线观看成人| 国产欧美三级| 国产精品入口夜色视频大尺度| 亚洲一级黄色大片| 国产精品18久久久久久vr| 国产亚洲精品美女久久久m| 色综合888| 国产精品亲子伦对白| 免费看黄色a级片| 欧美伦理91| 欧美亚洲日本一区| 丰满少妇一区二区三区专区| 老牛影视av一区二区在线观看| 亚洲深夜福利在线| 国产又黄又爽又无遮挡| 99精品久久久| 国产精品视频久久| 亚洲国产www| 久久久久久久久久久久久久久99| 亚洲啪啪av| 91www在线| 欧美日韩五月天| 91porn在线| 精品av一区二区| 欧美日韩爱爱视频| 色婷婷久久综合中文久久蜜桃av| 国产精品自在在线| 久久久com| 欧美激情二区| 日韩欧中文字幕| 国产乱码一区二区三区四区| 老汉色老汉首页av亚洲| 久久精品人人做人人爽| 国产精品美女久久久久av爽| 美女视频黄 久久| 国产伦精品一区二区| 91精彩视频在线播放| 亚洲高清免费观看| 久热精品在线播放| 台湾佬综合网| 欧美激情免费视频| 国产一区二区在线视频聊天| 91丨九色丨蝌蚪丨老版| 亚洲国产精品女人| 秋霞国产精品| 亚洲精品久久久久中文字幕欢迎你 | 高潮无码精品色欲av午夜福利| 国产在线视频一区二区| 日本电影一区二区三区| a级片在线免费观看| 欧美日本乱大交xxxxx| 成人免费毛片糖心| 亚洲电影在线| 懂色中文一区二区三区在线视频 | 亚洲理论电影片| 成人97在线观看视频| 最新中文字幕免费| 久久一区二区三区四区| 国产欧美日韩网站| jazzjazz国产精品久久| 久久人人爽亚洲精品天堂| 懂色av中文字幕| 91在线观看高清| 欧美日韩福利在线| 91麻豆精品激情在线观看最新 | 日本久久久网站| 国产麻豆精品| 久久香蕉频线观| 亚洲无码精品国产| 国产精品美女久久久久久久| 激情综合网俺也去| 欧美伦理影院| 国产精品电影一区| 国产一二三在线观看| 日韩欧美在线免费| 黄色录像a级片| 亚洲深夜激情| 久久资源av| 超碰国产一区| 亚洲欧美国产va在线影院| 天堂中文在线网| 99国产麻豆精品| 中文字幕在线观看不卡视频| 精品丰满人妻无套内射| 超碰97久久国产精品牛牛| 久久99精品久久久久久琪琪| 国产三级在线观看视频| 亚洲摸摸操操av| 18禁一区二区三区| 亚洲视频碰碰| 久久久一本精品99久久精品| 裤袜国产欧美精品一区| 永久免费看mv网站入口亚洲| av首页在线观看| 国产精品久久午夜夜伦鲁鲁| 色婷婷激情视频| 亚洲欧美综合| 国产一区免费在线| 日本乱码一区二区三区不卡| 亚洲日韩中文字幕| 中文字幕av网站| 亚洲免费av网站| 亚洲一区二区三区四区av| 亚洲区国产区| 日本一区免费观看| 亚洲国产91视频| 久久6精品影院| 亚洲日本中文字幕在线| 欧美在线视频全部完| 黄色a级片在线观看| 成人黄色网址在线观看| 国产熟人av一二三区| 欧美gayvideo| 国产 高清 精品 在线 a| 伊伊综合在线| 久久av红桃一区二区小说| 天天综合在线视频| 欧美老肥妇做.爰bbww| 久久久久久国产精品免费播放| 不卡视频一二三四| 三级a三级三级三级a十八发禁止| 欧美高清一区| 欧美亚洲免费高清在线观看| 999色成人| 91爱视频在线| 怡红院av在线| 亚洲日韩中文字幕在线播放| 国产色在线视频| 色悠悠亚洲一区二区| 爱爱视频免费在线观看| 久久色在线观看| 手机精品视频在线| 欧美专区一区二区三区| 高清无码一区二区在线观看吞精| 九九久久电影| 国产精品一区二区欧美黑人喷潮水 | 久色乳综合思思在线视频| 午夜福利理论片在线观看| 欧美日高清视频| 色婷婷在线观看视频| 国产精品的网站| 亚洲第一黄色网址| 国产东北露脸精品视频| 中文字幕有码av| 亚洲深夜激情| 97视频在线免费| 亚洲有吗中文字幕| 色涩成人影视在线播放| 欧洲精品一区| 国产精品久久久久久久免费大片 | 欧美精品1区2区| 免费无码国产精品| 午夜av电影一区| 久久午夜鲁丝片午夜精品| 国产精品日产欧美久久久久| 人人妻人人澡人人爽人人精品| 国产盗摄女厕一区二区三区| 亚洲制服中文字幕| 免费观看日韩av| 天天碰免费视频| 久久永久免费| 精品一卡二卡三卡| 国产视频欧美| 91九色丨porny丨国产jk| 欧美在线不卡| 成年人三级视频| 国产精品久久久久久影院8一贰佰 国产精品久久久久久麻豆一区软件 | 国产成人免费视频一区| 国产三级精品三级在线| 麻豆视频观看网址久久| 色片在线免费观看| 日韩专区欧美专区| av无码精品一区二区三区| 久久精品官网| 日韩手机在线观看视频| 天堂午夜影视日韩欧美一区二区| 777久久久精品一区二区三区| 亚洲激情国产| 无罩大乳的熟妇正在播放| 亚洲人人精品| 18岁网站在线观看| 麻豆精品91| 亚洲成人福利在线观看| 奇米色一区二区| 天美星空大象mv在线观看视频| 日本亚洲最大的色成网站www| 国产自偷自偷免费一区| 日韩电影一二三区| 91视频这里只有精品| 久久精品国产免费看久久精品| www.久久91| 韩国一区二区三区| 日本久久久久久久久久| 97超碰欧美中文字幕| 深爱五月激情网| 中文字幕精品—区二区四季| www.黄色com| 一区二区三区四区视频精品免费| 久草免费在线视频观看| 黄色一区二区在线观看| 影音先锋在线国产| 欧美三级日韩三级| 国产女主播福利| 欧美精品一区二区三区四区 | 91麻豆国产福利在线观看| 亚洲av无码一区二区三区人| 日本一区二区久久| 极品久久久久久| 五月天一区二区| 性高潮视频在线观看| 欧美精品丝袜久久久中文字幕| 精品人妻aV中文字幕乱码色欲| 精品国产成人在线影院| 激情福利在线| 美女久久久久久久久久久| 51漫画成人app入口| 国产成人久久精品| 成人在线分类| 欧美精品免费观看二区| 四虎成人av| 国产精品网站免费| 日韩精品1区2区3区| 91丨porny丨九色| 久久免费视频一区| 国产一二三四区| 欧美性猛交xxxx免费看久久久| 91在线公开视频| 日韩久久免费视频| 色网站免费在线观看| 91精品国产高清久久久久久91 | 6080yy午夜一二三区久久| 日韩一卡二卡在线| 久久精品国产亚洲精品2020| 成人av观看| 不卡日韩av| 日本大胆欧美| 黄色成人在线看| 国内成人自拍视频| 免费看污片网站| 亚洲国产精品天堂| 91影院在线播放| 亚洲人成在线播放| 超免费在线视频| 成人观看高清在线观看免费| 亚洲最好看的视频| 青青青青在线视频| 激情五月婷婷综合| 99在线视频免费| 黑人精品xxx一区一二区| 亚洲国产视频一区二区三区| 久久精品电影网| 成人免费毛片嘿嘿连载视频…| 国产欧美日韩综合一区在线观看| 天天射—综合中文网| 538在线视频观看| 91色视频在线| 国产污片在线观看| 欧美大片在线观看一区二区| 国产剧情在线| 国产中文日韩欧美| 日韩欧美精品一区| 久久久久狠狠高潮亚洲精品| av在线不卡网| 久久免费在线观看视频| 欧美一区二区在线免费播放| 一级毛片视频在线| 国产精品免费一区豆花| 精品久久久久久久| 可以免费在线看黄的网站| 91欧美一区二区| 日韩三级av在线| 亚洲国产精品电影| а√在线中文在线新版| 国产精品久久久久久久天堂第1集 国产精品久久久久久久免费大片 国产精品久久久久久久久婷婷 | 国产精品福利网站| 国产99精品| 国产精品久久久久9999小说| 国产亚洲一二三区| 无码人妻熟妇av又粗又大| 亚洲偷欧美偷国内偷| 久久xxx视频| 亚洲精品美女久久7777777| 日韩av午夜在线观看| 蜜桃无码一区二区三区| 在线视频一区二区三区| 丰满岳乱妇国产精品一区| 欧美精品一区二区免费| av在线亚洲色图| 欧美 丝袜 自拍 制服 另类| 国产99精品国产| 日韩手机在线观看| 亚洲精品一区二区三区不| 高潮一区二区| 免费av在线一区二区| 日产国产欧美视频一区精品| 成人免费视频入口| 4438成人网| av电影院在线看| 欧美裸体网站| 日韩不卡一区二区| 日本女人性生活视频| 日韩视频免费观看高清完整版在线观看| 日本伦理一区二区| 国产伦视频一区二区三区| 免费亚洲婷婷| 亚洲国产精品一区二区久久hs| 欧美精品高清视频| av影院在线免费观看| 任我爽在线视频精品一| 蓝色福利精品导航| 久久免费视频精品| 亚洲色图25p| 久久伊人国产| 日韩av中文字幕第一页| 久久久久国产精品厨房| 国产欧美熟妇另类久久久| 欧美日韩高清在线观看| 亚洲老女人视频免费| 国内自拍在线观看| 久久色中文字幕| 国产精品伦一区二区三区| 国色天香2019中文字幕在线观看| 国产精品羞羞答答在线观看| 日韩精品视频一二三| 亚洲444eee在线观看| 黄色免费网站在线| 成人在线看片| 丝袜美腿亚洲综合|