java多線程中關於原子操作

來源:互聯網
上載者:User

標籤:

各種不同的情況保證資料的正確性,完整性。

public class TestMultiThread implements Runnable {    private static int i;    private static volatile Integer vi = 0;    private static AtomicInteger ai = new AtomicInteger();    private static Integer si = 0;    private static Integer ia = 1;    private static int ri;    private static AtomicInteger flag = new AtomicInteger();    private static Lock lock = new ReentrantLock();   //如果lock不加static關鍵字時,那麼每一個線程將鎖住的是具體的對象,                                                      //而不是這個類。就會照成資料的不正確性    @Override    public void run() {        for (int k = 0; k < 200000; k++) {            i++;    //不是原子操作,此處含有三步(取得i的值,i+1,把i+1後的結果賦值給i)結果將有異常。當一條線程執行到i+1時,還沒有賦值,另一線程i+1並賦值。            vi++;    //同上,②解釋            ai.incrementAndGet();    //可以用原子方式更新的 int 值。以原子方式將當前值加 1.它只有一步操作,隨便哪個線程執行都將只有這一步。                    // synchronized(si){                                        // 此方法會照成si的值不對,是應為同步語句鎖定的是對象,用Integer作為對象鎖來使用,這本身沒有任何問題。            // si++;                    // 但同步體裡的操作偏偏是更改當前的鎖對象,結果就是前的對象鎖其實已經改變了,不是針對唯一的一個對象加鎖,所以會出現問題。                                        // 也因此,換一個公用對象就能解決問題。                                        // 在++操作中其實有一個賦值操作,這時對象已經改變,或者說是非原子操作                    // }            synchronized (ia) {   //用不變的ia作為鎖對象就能保證資料的正確性                si++;            }            lock.lock();   //此處的lock鎖必須為static的            try {                ri++;            } finally {                lock.unlock();            }        }        flag.incrementAndGet();    }    public static void main(String[] args) throws InterruptedException {        TestMultiThread t1 = new TestMultiThread();        TestMultiThread t2 = new TestMultiThread();        ExecutorService exec1 = Executors.newCachedThreadPool();        ExecutorService exec2 = Executors.newCachedThreadPool();        exec1.execute(t1);        exec2.execute(t2);        while (true) {            if (flag.intValue() == 2) {                System.out.println("i>>>>>" + i);                System.out.println("vi>>>>>" + vi);                System.out.println("ai>>>>>" + ai);                System.out.println("si>>>>>" + si);                System.out.println("ri>>>>>" + ri);                break;            }            Thread.sleep(50);        }    }}

結果:

i>>>>>398950
vi>>>>>386295
ai>>>>>400000
si>>>>>400000
ri>>>>>400000

 

解釋②:

在 java 記憶體回收整理一文中,描述了jvm運行時刻記憶體的分配。其中有一個記憶體地區是jvm虛擬機器棧,每一個線程運行時都有一個線程棧,

線程棧儲存了線程運行時候變數值資訊。當線程訪問某一個對象時候值的時候,首先通過對象的引用找到對應在堆記憶體的變數的值,然後把堆記憶體

變數的具體值load到執行緒區域記憶體中,建立一個變數副本,之後線程就不再和對象在堆記憶體變數值有任何關係,而是直接修改副本變數的值,

在修改完之後的某一個時刻(線程退出之前),自動把線程變數副本的值回寫到對象在堆中變數。這樣在堆中的對象的值就產生變化了。

java多線程中關於原子操作

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.