您好,登錄后才能下訂單哦!
這期內容當中小編將會給大家帶來有關Java自增操作的原子性是什么,文章內容豐富且以專業的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。
最近在工作中和一個同事因為自增是不是原子性操作爭論的面紅耳赤,那Java的自增操作到底是不是原子性操作呢,答案是否的,即Java的自增操作不是原子性操作。
1.首先我們先看看Bruce Eckel是怎么說的:
In the JVM an increment is not atomic and involves both a read and a write. (via the latest Java Performance Tuning Newsletter)
意思很簡單,就是說在jvm中自增不是原子性操作,它包含一個讀操作和一個寫操作。
2.以上可能還不能讓你信服,要想讓人心服口服,就必須用代碼說話。正如FaceBook的文化一樣:代碼贏得爭論。那我們就看一段代碼:
以下的代碼是用100個線程同時執行自增操作,每個線程自增100次,如果自增操作是原子性操作的話,那么執行完amount的值為10,000。運行代碼之后,你會發現amount的值小于10,000,這就說明自增操作不是原子性的
/** * * @author renrun.wu */ public class MultiThread implements Runnable { private int count; private int amount = 1; public MultiThread() { count = 100; } public MultiThread(int count) { this.count = count; } @Override public void run() { for (int i = 0; i < count; i++) { amount++; } } public static void main(String[] args) { ExecutorService executorService = Executors.newCachedThreadPool(); MultiThread multiThread =new MultiThread(); for (int i = 0; i < 100; i++) { executorService.execute(multiThread); } executorService.shutdown(); try { Thread.sleep(60000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(multiThread.amount); } }
3.如果以上還不能讓你信服的話,也沒關系。我們就把自增操作反編譯出來,看看java字節碼是怎么操作的
以下是一個簡單的自增操作代碼
public class Increment { private int id = 0; public void getNext(){ id++; } }
我們看看反編譯之后的Java字節碼,主要關注getNext()方法內部的Java字節碼。
public class Increment extends java.lang.Object{ public Increment(); Code: : aload_0 : invokespecial #1; //Method java/lang/Object."<init>":()V : aload_0 : iconst_0 : putfield #2; //Field id:I : return public void getNext(); Code: : aload_0 //加載局部變量表index為0的變量,在這里是this : dup //將當前棧頂的對象引用復制一份 : getfield #2; //Field id:I,獲取id的值,并將其值壓入棧頂 : iconst_1 //將int型的值1壓入棧頂 : iadd //將棧頂兩個int類型的元素相加,并將其值壓入棧頂 : putfield #2; //Field id:I,將棧頂的值賦值給id : return }
很明顯,我們能夠看到在getNext()方法內部,對于類變量id有一個先取值后加一再賦值的過程。因此,我們可以很肯定的說Java中的自增操作不是原子性的。
4.也許你會問,那局部變量的自增操作是否是原子性的。好,我們在看看一下代碼:
public class Increment { public void getNext(){ int id = 0; id++; } }
我們再看看反編譯之后的Java字節碼,主要還是關注getNext()方法內部的Java字節碼。
public class Increment extends java.lang.Object{ public Increment(); Code: : aload_0 : invokespecial #1; //Method java/lang/Object."<init>":()V : return public void getNext(); Code: : iconst_0 : istore_1 : iinc 1, 1 : return }
與全局變量的自增操作相比,很明顯局部變量的自增操作少了getfield與putfield操作。而且對于局部變量來說,它無論如何都不會涉及到多線程的操作,因此局部變量的自增操作是否是原子操作也就顯得不那么重要了。
上述就是小編為大家分享的Java自增操作的原子性是什么了,如果剛好有類似的疑惑,不妨參照上述分析進行理解。如果想知道更多相關知識,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。