国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - Java多線程CAS操作原理代碼實例解析

Java多線程CAS操作原理代碼實例解析

2020-07-26 00:03AmourLee Java教程

這篇文章主要介紹了Java多線程CAS操作原理代碼實例解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下

CAS操作號稱無鎖優化,也叫作自旋;對于一些常見的操作需要加鎖,然后jdk就提供了一些以Atomic開頭的類,這些類內部自動帶了鎖,當然這里的鎖并非是用synchronized來實現的,而是通過CAS操作來實現的;

一、下面是 AtomicInteger 的使用:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package com.designmodal.design.juc01;
 
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
 
/**
 * @author D-L
 * @Classname T03_AtomicInteger
 * @Version 1.0
 * @Description 使用 AtomicInteger 類解決常見的 多線程count++
 *        其內部使用了CAS操作來保證原子性 但是不能保證多個方法連續調用都是原子性
 * @Date 2020/7/21 0:35
 */
public class T03_AtomicInteger {
  //使用AtomicInteger類
  AtomicInteger count = new AtomicInteger(0);
 
  public void m(){
    for (int i = 0; i < 10000; i++) {
      //等同于 在 count++ 上加鎖
      count.incrementAndGet();
    }
  }
 
  public static void main(String[] args) {
    T03_AtomicInteger t = new T03_AtomicInteger();
    List<Thread> threads = new ArrayList<>();
    for (int i = 0; i < 10; i++) {
      threads.add(new Thread(t::m , "Thread" + i));
    }
    threads.forEach((o) -> o.start());
    threads.forEach(o ->{
      try {
        o.join();
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    });
 
    System.out.println(t.count);
  }
}

二、當然達到使用的級別很簡單,看一下API就好了,通過上面的小程序,下面主要來聊一聊原理:

1、通過源碼分析AtomicInteger

首先小程序中定義了一個 AtomicInteger 類型的變量count;

?
1
2
3
4
AtomicInteger count = new AtomicInteger(0);
public void add(){
 count.incrementAndGet();
}

調用了AtomicInteger類中incrementAndGet();

?
1
2
3
4
5
6
7
8
/**
   * Atomically increments by one the current value.
   *
   * @return the updated value
   */
  public final int incrementAndGet() {
    return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
  }

調用unsafe類中的 getAndAddInt(Object var1, long var2, int var4)方法;

?
1
2
3
4
5
6
7
8
9
10
11
12
public native int getIntVolatile(Object var1, long var2);
public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);
 
 
 public final int getAndAddInt(Object var1, long var2, int var4) {
    int var5;
    do {
      var5 = this.getIntVolatile(var1, var2);
    } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));
 
    return var5;
  }

這里通過以上三步的操作,最終會進入Unsafe類這里調用的 compareAndSwapInt 意思就是比較然后交換,通過一個while循環,在這里轉呀轉,直到修改成功;

CAS(compareAndSwap)(比較并交換):原來想改變的值為0 ,現在想修改成1 ,這里想做到線程安全就必須要加synchronized,現在想用另外一種方式來替換加鎖的方法,就是所謂的CAS操作;你可以把它想象成擁有三個參數的方法cas(V , Expected , NewValue); 第一個參數V是你要改的那個值,Expected第二個參數是你期望當前的值是多少(也就是如果沒有線程修改的時,這個值應該是多少,如果不是期望值那就證明有別的線程修改過),NewValue是要設置的新值;

Java多線程CAS操作原理代碼實例解析

上圖簡單模擬了CAS操作的過程,當線程1和線程2同時讀取了共享變量count = 0;在線程1修改的過程中,線程2已經將count值修改為1,那么在線程1修改的時候發現Expected值和V已經匹配不上了,證明已經有線程快我一步將count值改了(可能這里并發量大的時候已經有n多個線程已經修改過了),怎么辦呢?那我只能將我的期望值修改成V的值、newValue 在這基礎上加1,然后繼續在這自旋操作,直到修改成功,這就是自旋操作;

2、Unsafe類(java并發包底層實現的核心)

CAS操作不需要加鎖是如何做到的呢?原因就在于Unsafe這個類,這個類除了你使用反射之外,你是不能夠直接使用的,這里不能使用的原因和ClassLoader有關系,所有AtomicXXX 類內部都是CompareAndSwap / CompareAndSet(新版jdk),這個類中存在好多native方法;

Unsafe類使Java擁有了像C語言的指針一樣操作內存空間的能力,一旦能夠直接操作內存,這也就意味著(1)不受JVM管理,也就意味著無法被GC,需要我們手動GC,稍有不慎就會出現內存泄漏。(2)Unsafe的不少方法中必須提供原始地址(內存地址)和被替換對象的地址,偏移量要自己計算,一旦出現問題就是JVM崩潰級別的異常,會導致整個JVM實例崩潰,表現為應用程序直接crash掉。(3)直接操作內存,也意味著其速度更快,在高并發的條件之下能夠很好地提高效率。

CAS:CompareAndSwap,內存偏移地址(var2),預期值(var4),新值(var5)。如果變量在當前時刻的值和預期值expected相等,嘗試將變量的值更新為新值(var5)。如果更新成功,返回true;否則,返回false。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
   * CAS操作 :Unsafe類中的本地方法 由于Java語言無法訪問操作系統底層信息(比如:底層硬件設備等),
   * 這時候就需要借助C C++語言來完成了
   * @param var1 對象
   * @param var2 偏移量
   * @param var4 期望值
   * @param var5 新值
   * @return 修改成功返回true 失敗返回false
   */
  public final native boolean compareAndSwapObject(Object var1, long var2, Object var4, Object var5);
 
  public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);
 
  public final native boolean compareAndSwapLong(Object var1, long var2, long var4, long var6);

三、CAS操作帶來的ABA問題

ABA問題說白了就是在線程進行CAS操作過程中有多個線程對這個共享變量進行修改,有加有減,兜兜轉轉又回到起始值,這時該線程渾然不知;打個不恰當的比喻:這個過程就好像你前女友跟你分手以后,在時隔一年之后又找你復合來了,說兜兜轉轉還是覺得你好,在此期間你前女友已經換了幾個男朋友你卻渾然不知,那個好看的她穿著你喜歡的小短裙,扎著清純的馬尾辮又回來,好了言歸正傳,意思就是結果是你期望的,可是這個值是經過很多版本的。

下面簡單模擬ABA操作圖:

Java多線程CAS操作原理代碼實例解析

如何解決ABA問題呢?

如果是int類型,最終的值也是你期望的,真的是沒有所謂,你也不用去糾結這問題;如果你確實就想管一管,那就加一個版本號,做一次修改操作加一,比較檢查時連帶版本號一起檢查。

基礎類型:沒有必要管,對你真的沒有所謂;

引用類型:就像是你女朋友和你分手之后又復合,中間經歷了多少個男朋友,這個是有所謂的,這時可以通過加版本號來解決;

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:https://www.cnblogs.com/dongl961230/p/13352744.html

延伸 · 閱讀

精彩推薦
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25 Weibo Article 26 Weibo Article 27 Weibo Article 28 Weibo Article 29 Weibo Article 30 Weibo Article 31 Weibo Article 32 Weibo Article 33 Weibo Article 34 Weibo Article 35 Weibo Article 36 Weibo Article 37 Weibo Article 38 Weibo Article 39 Weibo Article 40
主站蜘蛛池模板: 成人国产精品免费观看 | 黄色在线免费看 | 成年人在线免费观看网站 | 91视频免费观看 | 成人高清网站 | 高清久久 | 亚洲国产精品久久久久久 | 成人av网站在线观看 | 国产视频三区 | 免费看黄色一级大片 | 在线看一区 | 亚洲欧美一区二区三区不卡 | 99精品一区二区三区 | 成人欧美一区二区三区在线观看 | 国产毛片18片毛一级特黄日韩a | 12306影视午夜入口 | 欧美视频精品在线观看 | 中文在线资源 | 欧美一级在线 | 免费日本视频 | 91中文在线 | 欧洲精品一区 | 黄色精品| 97超碰免费 | 国产精品爱久久久久久久 | 久久美 | 热久久这里只有精品 | 国产视频亚洲 | 国产精品久久久 | 欧美第一页 | 亚洲综合无码一区二区 | 无码一区二区三区视频 | 国产偷亚洲偷欧美偷精品 | 91视频.com| 91 久久 | 日韩免费一区二区 | 精品一区电影 | 国产精品久久久久久亚洲调教 | 91国内外精品自在线播放 | 在线观看亚洲成人 | 久久久久久久国产精品 |