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

并發編程利器 Java CAS 原子類全解

開發 后端
本文將全面解析 Java 中的 CAS 原子類,探討其背后的原理、應用場景以及如何有效利用這些工具來提升程序的并發性能和安全性。

在現代軟件開發中,多線程編程已經成為構建高性能、高響應性應用程序的關鍵技術之一。然而,多線程環境下的數據一致性問題一直是開發者面臨的一大挑戰。為了解決這一難題,Java 平臺提供了多種并發控制工具和機制,其中 java.util.concurrent.atomic 包中的 CAS(Compare-and-Swap)原子類尤為突出。 

本文將全面解析 Java 中的 CAS 原子類,探討其背后的原理、應用場景以及如何有效利用這些工具來提升程序的并發性能和安全性。通過深入理解 CAS 機制,讀者將能夠更好地應對復雜的并發編程場景,編寫出更加健壯和高效的代碼。

一、什么是CAS

CAS全稱Compare-And-Swap,是一種無鎖編程算法,即比較當前的值與舊值是否相等若相等則進行修改操作(樂觀鎖機制),該類常用于多線程共享變量的修改操作。而其底層實現也是基于硬件平臺的匯編指令,JVM只是封裝其調用僅此而已。而本文會基于以下大綱展開對CAS的探討。

二、CAS基礎使用示例

如下所示,可以看出使用封裝CAS操作的AtomicInteger操作多線程共享變量無需我們手動加鎖,因為避免過多人為操作這就大大減少了多線程操作下的失誤。

使用原子類操作共享數據:

public class CasTest {
    private AtomicInteger count = new AtomicInteger();


    public void increment() {
        count.incrementAndGet();
    }
    // 使用 AtomicInteger 后,不需要加鎖,也可以實現線程安全
    public int getCount() {
        return count.get();
    }

    public static void main(String[] args) {

    }
}

使用sync鎖操作數據:

public class Test {
    private int i=0;
    public synchronized int add(){
        return i++;
    }
}

三、從源碼角度了解java如何封裝匯編的UNSAFE

代碼也很簡單,就是拿到具有可見性的volatile變量i,然后判斷i和當前對象paramObject對應的i值是否一致,若一致則說明沒被人該過,進而進行修改操作,反之自旋循環獲取在進行CAS。

public final int getAndAddInt(Object paramObject, long paramLong, int paramInt)
  {
    int i;
    do
      i = getIntVolatile(paramObject, paramLong);
    while (!compareAndSwapInt(paramObject, paramLong, i, i + paramInt));
    return i;
  }

  public final long getAndAddLong(Object paramObject, long paramLong1, long paramLong2)
  {
    long l;
    do
      l = getLongVolatile(paramObject, paramLong1);
    while (!compareAndSwapLong(paramObject, paramLong1, l, l + paramLong2));
    return l;
  }

  public final int getAndSetInt(Object paramObject, long paramLong, int paramInt)
  {
    int i;
    do
      i = getIntVolatile(paramObject, paramLong);
    while (!compareAndSwapInt(paramObject, paramLong, i, paramInt));
    return i;
  }

  public final long getAndSetLong(Object paramObject, long paramLong1, long paramLong2)
  {
    long l;
    do
      l = getLongVolatile(paramObject, paramLong1);
    while (!compareAndSwapLong(paramObject, paramLong1, l, paramLong2));
    return l;
  }

  public final Object getAndSetObject(Object paramObject1, long paramLong, Object paramObject2)
  {
    Object localObject;
    do
      localObject = getObjectVolatile(paramObject1, paramLong);
    while (!compareAndSwapObject(paramObject1, paramLong, localObject, paramObject2));
    return localObject;
  }

四、手寫Unsafe實現20個線程500次CAS自增

代碼邏輯和注釋如下,讀者可自行debug查看邏輯:

public class CasCountInc {

    private static Logger logger = LoggerFactory.getLogger(CasCountInc.class);

    // 獲取Unsafe對象
    private static Unsafe unsafe = getUnsafe();

    // 線程池數目
    private static final int THREAD_COUNT = 20;

    // 每個線程運行自增次數
    private static final int EVERY_THREAD_ADD_COUNT = 500;

    // 自增的count的值,volatile保證可見性
    private volatile int count = 0;

    // count字段的偏移量
    private static long countOffSet;

    private static Unsafe getUnsafe() {
        Unsafe unsafe = null;
        try {
            Field field = Unsafe.class.getDeclaredField("theUnsafe");
            field.setAccessible(true);
            unsafe = (Unsafe) field.get(null);
        } catch (Exception e) {
            logger.info("獲取unsafe失敗,失敗原因:[{}]", e.getMessage(), e);
        }
        return unsafe;
    }


    static {
        try {
            countOffSet = unsafe.objectFieldOffset(CasCountInc.class.getDeclaredField("count"));
        } catch (NoSuchFieldException e) {
            logger.error("獲取count的偏移量報錯,錯誤原因:[{}]", e.getMessage(), e);
        }
    }


    public void inc() {
        int oldCount = 0;
        //基于cas完成自增
        do {
            oldCount = count;
        } while (!unsafe.compareAndSwapInt(this, countOffSet, oldCount, oldCount + 1));
    }


    public static void main(String[] args) throws InterruptedException {
        CasCountInc casCountInc = new CasCountInc();
        CountDownLatch countDownLatch = new CountDownLatch(THREAD_COUNT);
        IntStream.range(0, THREAD_COUNT).forEach(i -> {
            new Thread(() -> {
                IntStream.range(0, EVERY_THREAD_ADD_COUNT).forEach((j) -> {
                    casCountInc.inc();
                });
                countDownLatch.countDown();
            }).start();
        });

        countDownLatch.await();

        logger.info("count最終結果為 [{}]", casCountInc.count);
    }
}

五、原子類簡介

1.原子類更新基本類型

原子類基本類型的格式為Atomic+包裝類名,這里筆者列舉幾個比較常用的:

  • AtomicBoolean: 原子更新布爾類型。
  • AtomicInteger: 原子更新整型。
  • AtomicLong: 原子更新長整型。

2.原子類更新數組類型

  • AtomicIntegerArray: 原子更新整型數組里的元素。
  • AtomicLongArray: 原子更新長整型數組里的元素。
  • AtomicReferenceArray: 原子更新引用類型數組里的元素。

對應我們給出AtomicIntegerArray原子操作數組的示例:

public class AtomicIntegerArrayDemo {


    public static void main(String[] args) throws InterruptedException {
        AtomicIntegerArray array = new AtomicIntegerArray(new int[] { 0, 0 });
        System.out.println(array);
//        索引1位置+2
        System.out.println(array.getAndAdd(1, 2));
        System.out.println(array);
    }
}

3.原子類更新引用類型

  • AtomicReference: 原子更新引用類型。
  • AtomicStampedReference: 原子更新引用類型, 內部使用Pair來存儲元素值及其版本號。
  • AtomicMarkableReferce: 原子更新帶有標記位的引用類型。

對應的我們給出原子操作引用類型的代碼示例:

import java.util.concurrent.atomic.AtomicReference;

public class AtomicReferenceTest {

    public static void main(String[] args){

        // 創建兩個Person對象,它們的id分別是101和102。
        Person p1 = new Person(101);
        Person p2 = new Person(102);
        // 新建AtomicReference對象,初始化它的值為p1對象
        AtomicReference ar = new AtomicReference(p1);
        // 通過CAS設置ar。如果ar的值為p1的話,則將其設置為p2。
        ar.compareAndSet(p1, p2);

        Person p3 = (Person)ar.get();
        System.out.println("p3 is "+p3);
        System.out.println("p3.equals(p1)="+p3.equals(p1));
        System.out.println("p3.equals(p2)="+p3.equals(p2));
    }
}



class Person {
    volatile long id;
    public Person(long id) {
        this.id = id;
    }
    public String toString() {
        return "id:"+id;
    }
}

六、原子類更新成員變量

通過原子類型操作成員變量大體有以下幾個更新器:

  • AtomicIntegerFieldUpdater: 原子更新整型的字段的更新器。
  • AtomicLongFieldUpdater: 原子更新長整型字段的更新器。
  • AtomicStampedFieldUpdater: 原子更新帶有版本號的引用類型
  • AtomicReferenceFieldUpdater: 上面已經說過此處不在贅述。

如下所示,我們創建一個基礎類DataDemo,通過原子類CAS操作字段值進行自增操作。

public class TestAtomicIntegerFieldUpdater {


    private static Logger logger = LoggerFactory.getLogger(TestAtomicIntegerFieldUpdater.class);

    public static void main(String[] args) {
        TestAtomicIntegerFieldUpdater tIA = new TestAtomicIntegerFieldUpdater();
        tIA.doIt();
    }

    /**
     * 返回需要更新的整型字段更新器
     *
     * @param fieldName
     * @return
     */
    public AtomicIntegerFieldUpdater<DataDemo> updater(String fieldName) {
        return AtomicIntegerFieldUpdater.newUpdater(DataDemo.class, fieldName);
    }

    public void doIt() {
        DataDemo data = new DataDemo();
        // 修改公共變量,返回更新前的舊值 0
        AtomicIntegerFieldUpdater<DataDemo> updater = updater("publicVar");
        int oldVal = updater.getAndIncrement(data);
        logger.info("publicVar 更新前的值[{}] 更新后的值 [{}]", oldVal, data.publicVar);


        // 更新保護級別的變量
        AtomicIntegerFieldUpdater<DataDemo> protectedVarUpdater = updater("protectedVar");
        int oldProtectedVar = protectedVarUpdater.getAndAdd(data, 2);
        logger.info("protectedVar 更新前的值[{}] 更新后的值 [{}]", oldProtectedVar, data.protectedVar);


        // logger.info("privateVar = "+updater("privateVar").getAndAdd(data,2)); 私有變量會報錯

        /*
         * 下面報異常:must be integer
         * */
//        logger.info("integerVar = "+updater("integerVar").getAndIncrement(data));
        //logger.info("longVar = "+updater("longVar").getAndIncrement(data));
    }


    class DataDemo {

        // 公共且可見的publicVar
        public volatile int publicVar = 0;
        // 保護級別的protectedVar
        protected volatile int protectedVar = 4;
        // 私有變量
        private volatile int privateVar = 5;

        // final 不可變量
        public final int finalVar = 11;

        public volatile Integer integerVar = 19;
        public volatile Long longVar = 18L;

    }

}
public class TestAtomicIntegerFieldUpdater {


    private static Logger logger = LoggerFactory.getLogger(TestAtomicIntegerFieldUpdater.class);

    public static void main(String[] args) {
        TestAtomicIntegerFieldUpdater tIA = new TestAtomicIntegerFieldUpdater();
        tIA.doIt();
    }

    /**
     * 返回需要更新的整型字段更新器
     *
     * @param fieldName
     * @return
     */
    public AtomicIntegerFieldUpdater<DataDemo> updater(String fieldName) {
        return AtomicIntegerFieldUpdater.newUpdater(DataDemo.class, fieldName);
    }

    public void doIt() {
        DataDemo data = new DataDemo();
        // 修改公共變量,返回更新前的舊值 0
        AtomicIntegerFieldUpdater<DataDemo> updater = updater("publicVar");
        int oldVal = updater.getAndIncrement(data);
        logger.info("publicVar 更新前的值[{}] 更新后的值 [{}]", oldVal, data.publicVar);


        // 更新保護級別的變量
        AtomicIntegerFieldUpdater<DataDemo> protectedVarUpdater = updater("protectedVar");
        int oldProtectedVar = protectedVarUpdater.getAndAdd(data, 2);
        logger.info("protectedVar 更新前的值[{}] 更新后的值 [{}]", oldProtectedVar, data.protectedVar);


        // logger.info("privateVar = "+updater("privateVar").getAndAdd(data,2)); 私有變量會報錯

        /*
         * 下面報異常:must be integer
         * */
//        logger.info("integerVar = "+updater("integerVar").getAndIncrement(data));
        //logger.info("longVar = "+updater("longVar").getAndIncrement(data));
    }


    class DataDemo {

        // 公共且可見的publicVar
        public volatile int publicVar = 0;
        // 保護級別的protectedVar
        protected volatile int protectedVar = 4;
        // 私有變量
        private volatile int privateVar = 5;

        // final 不可變量
        public final int finalVar = 11;

        public volatile Integer integerVar = 19;
        public volatile Long longVar = 18L;

    }

}

通過上述代碼我們可以總結出CAS字段必須符合以下要求:

  • 變量必須使用volatile保證可見性
  • 必須是當前對象可以訪問到的類型才可進行操作‘
  • 只能是實例變量而不是類變量,即不可以有static修飾符
  • 包裝類也不行

七、CAS的ABA問題

CAS更新前會檢查值有沒有變化,如果沒有變化則認為沒人修改過,在進行更新操作。這種情況下,若我們A值修改為B,B再還原為A。這種修改再還原的操作,CAS是無法感知是否變化的,這就是所謂的ABA問題。

1.AtomicStampedReference源碼詳解

源碼如下所示,可以看到AtomicStampedReference解決ABA問題的方式是基于當前修改操作的時間戳和元引用值是否一致,若一直則進行數據更新

public class AtomicStampedReference<V> {
    private static class Pair<T> {
        final T reference;  //維護對象引用
        final int stamp;  //用于標志版本
        private Pair(T reference, int stamp) {
            this.reference = reference;
            this.stamp = stamp;
        }
        static <T> Pair<T> of(T reference, int stamp) {
            return new Pair<T>(reference, stamp);
        }
    }
    private volatile Pair<V> pair;
    ....
    
    /**
      * expectedReference :更新之前的原始引用值
      * newReference : 新值
      * expectedStamp : 預期時間戳
      * newStamp : 更新后的時間戳
      */
    public boolean compareAndSet(V   expectedReference,
                             V   newReference,
                             int expectedStamp,
                             int newStamp) {
        // 獲取當前的(元素值,版本號)對
        Pair<V> current = pair;
        return
            // 引用沒變
            expectedReference == current.reference &&
            // 版本號沒變
            expectedStamp == current.stamp &&
           //可以看到這個括號里面用了一個短路運算如果當前版本與新值一樣就說更新過,就不往下走CAS代碼了
            ((newReference == current.reference &&
           
            newStamp == current.stamp) ||
            // 構造新的Pair對象并CAS更新
            casPair(current, Pair.of(newReference, newStamp)));
    }

    private boolean casPair(Pair<V> cmp, Pair<V> val) {
        // 調用Unsafe的compareAndSwapObject()方法CAS更新pair的引用為新引用
        return UNSAFE.compareAndSwapObject(this, pairOffset, cmp, val);
    }

2.AtomicStampedReference解決ABA問題示例

代碼示例,我們下面就用other代碼模擬干擾現場,如果other現場先進行CAS更新再還原操作,那么main線程的版本號就會過時,CAS就會操作失敗

/**
 * ABA問題代碼示例
 */
public class AtomicStampedReferenceTest {
    private static AtomicStampedReference<Integer> atomicStampedRef =
            new AtomicStampedReference<>(1, 0);

    public static void main(String[] args) {
        Thread main = new Thread(() -> {
            System.out.println("操作線程" + Thread.currentThread() + ",初始值 a = " + atomicStampedRef.getReference());
            int stamp = atomicStampedRef.getStamp(); //獲取當前標識別
            try {
                Thread.sleep(1000); //等待1秒 ,以便讓干擾線程執行
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            boolean isCASSuccess = atomicStampedRef.compareAndSet(1, 2, stamp, stamp + 1);  //此時expectedReference未發生改變,但是stamp已經被修改了,所以CAS失敗
            System.out.println("操作線程" + Thread.currentThread() + ",CAS操作結果: " + isCASSuccess);
        }, "主操作線程");

        Thread other = new Thread(() -> {
            Thread.yield(); // 確保thread-main 優先執行
            atomicStampedRef.compareAndSet(1, 2, atomicStampedRef.getStamp(), atomicStampedRef.getStamp() + 1);
            System.out.println("操作線程" + Thread.currentThread() + ",【increment】 ,值 = " + atomicStampedRef.getReference());
            atomicStampedRef.compareAndSet(2, 1, atomicStampedRef.getStamp(), atomicStampedRef.getStamp() + 1);
            System.out.println("操作線程" + Thread.currentThread() + ",【decrement】 ,值 = " + atomicStampedRef.getReference());
        }, "干擾線程");

        main.start();
        other.start();
    }

}

3.AtomicMarkableReference解決對象ABA問題

AtomicMarkableReference,它不是維護一個版本號,而是維護一個boolean類型的標記,標記對象是否有修改,從而解決ABA問題。

public boolean weakCompareAndSet(V       expectedReference,
                                     V       newReference,
                                     boolean expectedMark,
                                     boolean newMark) {
        return compareAndSet(expectedReference, newReference,
                             expectedMark, newMark);
    }

八、常見面試題

1.CAS為什么比synchronized快(重點)

CAS工作原理是基于樂觀鎖且操作是原子性的,與synchronized的悲觀鎖(底層需要調用操作系統的mutex鎖)相比,效率也會相對高一些。

2.CAS是不是操作系統執行的?(重點)

不是,CAS是主要是通過處理器的指令來保證原子性的,在上面的講解中我們都知道CAS操作底層都是調用Unsafe的native修飾的方法,以AtomicInteger為例對應的底層的實現是Unsafe的compareAndSwapInt:

 public final native boolean compareAndSwapInt(Object o, long offset,
                                                  int expected,
                                                  int x);

對應的我們給出這段代碼的c語言實現,即位于:https://github.com/openjdk/jdk/blob/jdk8-b01/hotspot/src/share/vm/prims/unsafe.cpp的unsafe.cpp:

可以看到出去前兩個形參后續的參數與compareAndSwapInt列表一一對應,這段代碼執行CAS操作時,本質上就是調用cmpxchg指令(Compare and Exchange),cmpxchg指令會判斷當前服務器是否是多核,如果是則講LOCK前綴保證cmpxchg操作的原子性,反之就不加Lock前綴直接執行比對后修改變量值這種樂觀鎖操作。

對應源碼如下,它首先獲取字段的偏移地址,然后傳入預期值e與原值比較,如果一致,則將新結果x寫入原子操作變量內存中:

UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint e, jint x))
  UnsafeWrapper("Unsafe_CompareAndSwapInt");
  oop p = JNIHandles::resolve(obj);
  //獲取字段偏移量地址
  jint* addr = (jint *) index_oop_from_field_offset_long(p, offset);
  //比較如果期望值e和當前字段存儲的值一樣,則講值更新為x
  return (jint)(Atomic::cmpxchg(x, addr, e)) == e;
UNSAFE_END

3.CAS存在那些問題?

但即便如此CAS仍然存在兩個問題:

(1) 可能存在長時間CAS:如下代碼所示,這就是AtomicInteger底層的UNSAFE類如何進行CAS的具體代碼   ,可以看出這個CAS操作需要拿到volatile變量后在進行循環CAS才有可能成功這就很可能存在自旋循環,從而給CPU帶來很大的執行開銷。

public final int getAndAddInt(Object paramObject, long paramLong, int paramInt)
  {
    int i;
    do
     //獲取最新結果
      i = getIntVolatile(paramObject, paramLong);
      //通過cas自旋操作完成自增
    while (!compareAndSwapInt(paramObject, paramLong, i, i + paramInt));
    return i;
  }

(2) CAS只能對一個變量進行原子操作:為了解決這個問題,JDK 1.5之后通過AtomicReference使得變量可以封裝成一個對象進行操作

ABA問題:總所周知CAS就是比對當前值與舊值是否相等,在進行修改操作,假設我現在有一個變量值為A,我改為B,再還原為A,這樣操作變量值是沒變的?那么CAS也會成功不就不合理嗎?這就好比一個銀行儲戶想查詢概念轉賬記錄,如果轉賬一次記為1,如果按照ABA問題的邏輯,那么這個銀行賬戶轉賬記錄次數有可能會缺少。為了解決這個問題JDK 1.5提供了AtomicStampedReference,通過比對版本號在進行CAS操作,那么上述操作就會變為1A->2B->3A,由于版本追加,那么我們就能捕捉到當前變量的變化了。

4.AtomicInteger自增到10000后如何歸零

AtomicInteger atomicInteger=new AtomicInteger(10000);
atomicInteger.compareAndSet(10000, 0);

5.CAS 平時怎么用的,會有什么問題,為什么快,如果我用 for 循環代替 CAS 執行效率是一樣的嗎?(重點)

問題1: 一些需要并發計數并實時監控的場景可以用到。

 問題2: CAS存在問題:CAS是基于樂觀鎖機制,所以數據同步失敗就會原地自旋,在高并發場景下開銷很大,所以線程數很大的情況下不建議使用原子類。

 問題3:用 for 循環代替 CAS 存在問題: 如果并發量大的話,自旋的線程多了就會導致性能瓶頸。

 for 循環代替 CAS執行效率是否一樣:大概率是CAS快,原因如下:

  • CAS是native方法更接近底層
  • for循環為了保證線程安全可能會用到sync鎖或者Lock無論那種都需要上鎖和釋放的邏輯,相比CAS樂觀鎖來說開銷很大。
責任編輯:趙寧寧 來源: 寫代碼的SharkChili
相關推薦

2025-11-21 09:20:00

2025-07-23 08:12:10

2022-12-06 08:42:28

2023-12-14 07:36:16

Java并發原子類

2024-08-09 08:41:14

2023-12-01 08:54:50

Java原子類型

2020-12-11 11:11:44

原子類JavaCAS

2023-01-05 12:30:32

Redis

2021-03-11 00:05:55

Java高并發編程

2021-03-04 07:24:24

JavaSemaphore高并發

2021-03-18 00:14:29

JavaCyclicBarri高并發

2009-03-09 21:25:11

Linuxnagios開源

2024-12-27 09:08:25

2021-02-05 11:35:03

原子類數值變量

2025-05-30 07:10:19

2024-04-22 00:00:00

CASCPU硬件

2022-12-06 17:28:36

Java優化CAS操作

2021-04-26 17:23:21

JavaCAS原理

2017-09-19 14:53:37

Java并發編程并發代碼設計

2011-03-30 10:07:02

Zabbix安裝
點贊
收藏

51CTO技術棧公眾號

国产乱码精品一区二区三| 试看120秒一区二区三区| 国产亚洲美州欧州综合国| 国产精品久久中文| 国产一区二区视频在线观看免费| 四虎在线精品| 同产精品九九九| 艳色歌舞团一区二区三区| 不卡视频免费在线观看| 免费视频一区| 欧美成人在线免费| 美女被到爽高潮视频| 精品成人18| 色哟哟日韩精品| 成年在线观看视频| 国产小视频福利在线| 国产成人啪免费观看软件| 国产aⅴ夜夜欢一区二区三区| 精品国产精品国产精品| 亚洲aa在线| 精品精品国产高清a毛片牛牛| 久久综合伊人77777麻豆最新章节| 在线看女人毛片| 欧美激情一二三区| 久久波多野结衣| www.97超碰| 麻豆视频观看网址久久| 91精品国产精品| 欧美成人一区二区三区高清| 久久久影院免费| 亚洲毛片在线看| 香蕉久久久久久av成人| 91视频成人| 在线免费观看视频一区| 男女激情无遮挡| 国产蜜臀一区二区打屁股调教| 国产精品视频在线看| 蜜桃臀一区二区三区| 国产成人无码www免费视频播放| 久久97超碰色| 成人欧美一区二区三区在线湿哒哒| 天堂免费在线视频| 久久久久久久欧美精品| 2018日韩中文字幕| 国产成人在线免费观看视频| 欧美淫片网站| 久99久在线视频| 亚洲 欧美 变态 另类 综合| 欧美激情欧美| 精品国产一区二区三区久久久| 成人在线观看免费高清| 激情五月综合| 国产一二三四五区| 国产麻豆91视频| 日日摸夜夜添夜夜添国产精品| 亚州国产精品久久久| 欧美日韩偷拍视频| 亚洲天堂免费| 色妞久久福利网| 亚洲精品天堂网| 人人狠狠综合久久亚洲婷| 国产亚洲精品日韩| 色欲狠狠躁天天躁无码中文字幕| 国模吧精品视频| 亚洲人av在线影院| 国产毛片欧美毛片久久久| 黑人操亚洲人| 久久精品国产96久久久香蕉| 波多野结衣久久久久| 久久精品青草| 欧美日韩国产成人| 国产一卡二卡在线| 国产精品亚洲欧美| 国产精品劲爆视频| 一区二区日韩视频| 国产剧情在线观看一区二区| av一区二区三区免费| 欧美一级淫片aaaaaa| 91女神在线视频| 四虎永久国产精品| mm1313亚洲国产精品美女| 一二三四社区欧美黄| 伊人再见免费在线观看高清版| 国产色婷婷在线| 色婷婷久久久久swag精品 | 国产精品日韩一区| 国产精品无码久久久久成人app| 国产成人小视频| 久久综合九九| 欧美成人hd| 性欧美大战久久久久久久久| 久久国产色av免费观看| **日韩最新| 亚洲精品成人久久久| www..com.cn蕾丝视频在线观看免费版 | 91超碰这里只有精品国产| 18禁一区二区三区| 欧美日中文字幕| 欧美激情网友自拍| 老熟妇一区二区三区啪啪| 国产精品91一区二区| 日本公妇乱淫免费视频一区三区| а√天堂官网中文在线| 福利一区视频在线观看| 制服丝袜中文字幕第一页| 精品国产影院| 日韩中文字在线| 超碰中文字幕在线| 国产成人av福利| 日韩视频在线观看国产| 大香伊人中文字幕精品| 欧美二区三区的天堂| 成年人网站免费看| 欧美va亚洲va日韩∨a综合色| 国产99久久久欧美黑人 | 天天天天天天天干| av资源站一区| 青草网在线观看| 懂色aⅴ精品一区二区三区| 亚洲精品国精品久久99热一| 久草视频免费播放| 韩国一区二区在线观看| 日韩福利影院| 肉色欧美久久久久久久免费看| 亚洲成人在线网| 1024手机在线视频| 久久99久久精品| 亚洲国产精品毛片| 亚洲精品永久免费视频| 亚洲成人在线网| 伊人365影院| 国产精品白丝av| 97超碰免费观看| 日韩美香港a一级毛片| 国产一区二区三区日韩欧美| 国内免费精品视频| 成人深夜视频在线观看| 国产欧美日韩小视频| 日本高清精品| 欧美另类老女人| a天堂视频在线| 亚洲天堂久久久久久久| 亚洲综合av在线播放| 成人久久一区| 国产美女91呻吟求| 网友自拍视频在线| 欧美精品一级二级| chinese全程对白| 国产乱码精品1区2区3区| 激情视频小说图片| 日韩一区二区三区高清在线观看| 欧美精品情趣视频| 午夜精品久久久久久久99| 亚洲图片自拍偷拍| 久久久久久久久免费看无码 | 久久久精品高清| 99国产**精品****| 91中文字幕一区| 国产在线xxx| 日韩av在线网站| 少妇高潮av久久久久久| 国产欧美日韩另类一区| 亚洲天堂伊人网| 欧美日韩视频一区二区三区| 国产精品免费在线播放| 人成在线免费网站| 一区二区亚洲欧洲国产日韩| 亚洲天堂久久久久| 亚洲精品国产无天堂网2021| 北京富婆泄欲对白| 老司机午夜精品视频| 亚洲精品一区二区三区樱花| 未满十八勿进黄网站一区不卡| 久久99青青精品免费观看| 亚洲精品字幕在线观看| 富二代精品短视频| www.99re6| www.日韩av| 九九热在线免费| 欧美成人国产| 欧美亚洲免费在线| 高清一区二区| 欧美在线一级视频| 精品美女在线观看视频在线观看 | 国产一区二区黄色| 巨胸喷奶水www久久久| 久久精品91久久香蕉加勒比| 可以免费观看的毛片| 色呦呦国产精品| 欧美成人精品一区二区免费看片| 久久女同性恋中文字幕| 一二三级黄色片| 久久精品一区二区国产| 亚洲精品国产suv一区88| 国产一区99| 国产精品国产三级国产专区53 | 欧美黄色免费看| 久久久久久9999| 男人女人拔萝卜视频| 久久久久网站| 水蜜桃色314在线观看| 色综合五月天| 欧美不卡在线一区二区三区| 久久久久久久久成人| 国产经典一区二区| 欧美野外wwwxxx| 精品国模在线视频| 美女欧美视频在线观看免费 | 最新av电影网站| 久久久久久日产精品| 色哟哟网站在线观看| 激情欧美日韩一区二区| 日本一极黄色片| 国内精品久久久久久久97牛牛 | 黄色精品视频网站| 青青精品视频播放| 6699嫩草久久久精品影院| www.精品av.com| 国产三级视频在线看| 亚洲精品456在线播放狼人| 国产乱码一区二区| 欧美色爱综合网| 无码人妻精品一区二区三区9厂| 亚洲成人免费在线观看| 欧美日韩综合一区二区| 成人免费小视频| 日本污视频网站| 久久久国产精品午夜一区ai换脸| yy1111111| 成人avav影音| 污片免费在线观看| 成人视屏免费看| 日韩综合第一页| 成人网在线免费视频| 久草免费资源站| 国产成人免费视频网站高清观看视频| 婷婷中文字幕在线观看| 麻豆成人久久精品二区三区小说| 日韩一级片播放| 日韩主播视频在线| www.99在线| 美腿丝袜亚洲色图| 奇米视频7777| 激情五月激情综合网| 性欧美在线视频| 国产一区二区福利| 永久看看免费大片| 国产不卡视频在线观看| 韩国三级视频在线观看| www.欧美.com| 中文人妻一区二区三区| 久久久精品黄色| 蜜桃视频最新网址| 亚洲色图19p| 国产一级免费av| 精品动漫一区二区三区| 亚洲免费黄色网址| 欧美特级限制片免费在线观看| 成人黄色片在线观看| 欧美日韩成人综合在线一区二区| 亚洲视频在线免费播放| 69成人精品免费视频| 精品国产无码AV| 精品国产一区二区三区久久久蜜月| 蜜桃91麻豆精品一二三区| 亚洲国产精久久久久久久| 全色精品综合影院| 中文字幕亚洲精品| 中文国产字幕在线观看| 97热精品视频官网| 精品日韩视频| 成人免费网站在线观看| 视频精品国内| 看欧美日韩国产| 日韩电影免费网址| 精品一区二区三区无码视频| 欧美一区=区| 黄色a级三级三级三级| av中文字幕亚洲| 亚洲 欧美 国产 另类| 亚洲已满18点击进入久久| 久草视频一区二区| 91精品国产综合久久香蕉麻豆| 天堂在线资源库| 爽爽爽爽爽爽爽成人免费观看| 性欧美猛交videos| 国产99久久精品一区二区永久免费| 自拍偷拍欧美日韩| 久久久久高清| 中文一区一区三区免费在线观看| www.av中文字幕| 精品一区二区免费看| 国产精品扒开腿做爽爽爽a片唱戏| 欧美国产日本视频| 国产精品变态另类虐交| 欧美日韩在线电影| 婷婷五月综合激情| 在线观看视频亚洲| 亚洲天堂免费电影| 91亚洲一区精品| 禁果av一区二区三区| 欧美狂野激情性xxxx在线观| 日本中文字幕一区二区视频 | 亚洲人成小说网站色在线| 亚洲欧美综合自拍| 精品久久久三级丝袜| 日韩成人影视| 国产97在线|亚洲| 福利欧美精品在线| 色爽爽爽爽爽爽爽爽| 三级在线观看一区二区| 亚洲视频天天射| 亚洲免费在线电影| 在线观看亚洲一区二区| 亚洲欧美在线x视频| 国产网红在线观看| 51国偷自产一区二区三区| 日韩大片在线观看| 日韩中文字幕免费在线| 97精品久久久午夜一区二区三区| 青青草原在线免费观看视频| 5566中文字幕一区二区电影 | 欧美日本成人| 国产精品秘入口18禁麻豆免会员| 国产成人亚洲精品青草天美| avtt天堂在线| 欧美丰满嫩嫩电影| 欧美成人xxx| 成人h视频在线观看播放| 欧美日韩中文一区二区| 男女爽爽爽视频| 国产网红主播福利一区二区| 国内自拍视频在线播放| 日韩电影免费在线观看中文字幕 | 欧美激情五月| 中文字幕一区二区三区四| 亚洲视频一区在线观看| 一级黄色片在线播放| 日韩在线www| 外国成人毛片| 久久久久久久久久久久久国产| 精品一区二区三区视频| av黄色免费在线观看| 欧美日韩欧美一区二区| 日韩美女网站| 亚洲影院在线看| 欧美激情在线| 中文字幕第九页| 五月激情综合色| 色吊丝在线永久观看最新版本| 国产91精品视频在线观看| 伊人久久综合影院| 亚洲爆乳无码专区| 亚洲国产精品ⅴa在线观看| 欧美视频xxxx| 日韩在线视频一区| 精品国产不卡一区二区| 成年人网站国产| 91麻豆swag| 中文字幕+乱码+中文乱码www| 中文字幕在线亚洲| 99er精品视频| 福利视频一二区| www日韩大片| 在线播放亚洲精品| 欧美成人精品激情在线观看| 成人18夜夜网深夜福利网| 自慰无码一区二区三区| 久久精品亚洲精品国产欧美 | 今天免费高清在线观看国语| 成人午夜精品一区二区三区| 成人在线免费看视频| 在线日韩精品视频| 日韩一二三区在线观看| 337p粉嫩大胆噜噜噜鲁| 中文字幕不卡的av| 国产福利视频导航| 97久久精品视频| 日本道不卡免费一区| 成年人网站av| 精品福利在线视频| www 日韩| 草莓视频一区| 日本va欧美va瓶| 精品无码人妻一区二区三区| 国产亚洲精品美女| 97一区二区国产好的精华液| 日本熟妇人妻中出| 夜夜嗨av一区二区三区四季av| 九色在线免费| aaa级精品久久久国产片| 日韩国产一区二| 国产一级性生活| 色噜噜国产精品视频一区二区 | 日韩视频在线一区| 欧美大奶一区二区| 国产永久免费网站| 色婷婷综合久久久中文一区二区| 亚洲欧美成人影院| 亚洲欧美国产精品桃花|