1. 程式人生 > >1.Atomic的原子自增運算

1.Atomic的原子自增運算

1.

最好將thread.activeCount的值擴大一點兒,因為過小的話會導致記憶體切換的過於頻繁,容易導致程式崩潰

執行結果如下:

程式碼原始碼:

import org.omg.PortableServer.THREAD_POLICY_ID;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * Atomic變數自增運算測試
 */
public class AtomicTest {
    public static AtomicInteger race = new AtomicInteger(0);

    public static void increase() {
        race.incrementAndGet();
    }

    private static final int THREADS_COUNT = 20;


    public static void main(String[] args) throws Exception {
        Thread[] threads = new Thread[THREADS_COUNT]; //定義一組threas的陣列集合
        for (int i = 0; i < THREADS_COUNT; i++) { //20個執行緒進行單個迴圈
            threads[i] = new Thread(new Runnable() {  //單個執行緒進行實現runable的操作
                @Override
                public void run() {
                    for (int i = 0; i < 10000; i++){
                        increase(); //對increase進行自增操作,執行結果如下,內部迭代的工程
                    }
                }
            });
            //啟動當前狀態的i執行緒,因此要寫在for迴圈裡面
            threads[i].start();
        }
        while(Thread.activeCount()>10);
        Thread.yield();
        System.out.println(race);//正確輸出結果為10000(單個程序自增的次數)*20(總的程序數)
                                 //因此自增結果應該為200000,但是實際結果並不是,而是偏小
    }
}

先得出輸出結果,如下;

程式碼如下:

import org.omg.PortableServer.THREAD_POLICY_ID;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * Atomic變數自增運算測試
 */
public class AtomicTest {
    //public static AtomicInteger race = new AtomicInteger(0);
    public static int race = 1;
    public static void increase() {
        race++;
    }

    private static final int THREADS_COUNT = 20;


    public static void main(String[] args) throws Exception {
        Thread[] threads = new Thread[THREADS_COUNT]; //定義一組threas的陣列集合
        for (int i = 0; i < THREADS_COUNT; i++) { //20個執行緒進行單個迴圈
            threads[i] = new Thread(new Runnable() {  //單個執行緒進行實現runable的操作
                @Override
                public void run() {
                    for (int i = 0; i < 100; i++){
                        increase(); //對increase進行自增操作,執行結果如下,內部迭代的工程
                    }
                }
            });
            //啟動當前狀態的i執行緒,因此要寫在for迴圈裡面
            threads[i].start();
        }
        while(Thread.activeCount()>4);
        //Thread.yield();
        System.out.println(race);//正確輸出結果為100(單個程序自增的次數)*20(總的程序數)
                                 //因此自增結果應該為2000,但是實際結果並不是,而是偏小
    }
}

//因此可知這種方法也是執行緒相對而言,並不是安全的。

但是AntomicInteger操作之後:

如下:

得出了正確的結果:

程式碼原始碼如下:

import org.omg.PortableServer.THREAD_POLICY_ID;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * Atomic變數自增運算測試
 */
public class AtomicTest {
    public static AtomicInteger race = new AtomicInteger(0);
    public static void increase() {
        race.incrementAndGet();
    }

    private static final int THREADS_COUNT = 20;


    public static void main(String[] args) throws Exception {
        Thread[] threads = new Thread[THREADS_COUNT]; //定義一組threas的陣列集合
        for (int i = 0; i < THREADS_COUNT; i++) { //20個執行緒進行單個迴圈
            threads[i] = new Thread(new Runnable() {  //單個執行緒進行實現runable的操作
                @Override
                public void run() {
                    for (int i = 0; i < 100; i++){
                        increase(); //對increase進行自增操作,執行結果如下,內部迭代的工程
                    }
                }
            });
            //啟動當前狀態的i執行緒,因此要寫在for迴圈裡面
            threads[i].start();
        }
        while(Thread.activeCount()>2);
        //Thread.yield();
        System.out.println(race);//正確輸出結果為100(單個程序自增的次數)*20(總的程序數)
                                 //因此自增結果應該為2000,但是實際結果並不是,而是偏小
    }
}

使用int進行定義的時候,race這是不安全的機制,詳細程式碼,可以複製拿去驗證,但是使用AtomicInteger盡享定義就不一樣的了,因為其定義了race之後,呼叫方法,incrementAndGet()方法,但是該方法是原子性的可以確保其執行緒是安全的。

驗證的時候,Thread.activeCount>不要設定的過大。這個

問題會專門寫個專題擴充套件一下:

Thread.activeCount() 方法返回活動執行緒的當前執行緒的執行緒組中的數量,已你現在的程式(執行緒中間過程短,一下就結束了)所以你Thread.activeCount()時為1,你可以System.out.println(Thread.activeCount())控制檯輸出試試

1的話,當前執行緒組的書,數目為1,是會導致切換過快,計算機進行假死的情況的。

因此需要設定成2以及以上即可。

其中incrementAndGet()方法,跟進去,檢視如下所示:

繼承了Number類以及進行了序列化的操作:

final表明了這個是不可能輕易被繼承的,一定程度保證了其原子性

然後再跟進一個getAndAddInt繼續去跟進下一步:

對於getIntVolatile()這個方法進行跟進如下所示;

擴充套件如下所示:

1。native 是用做java 和其他語言(如c++)進行協作時用的
也就是native 後的函式的實現不是用java寫的
2。既然都不是java,那就別管它的原始碼了