實戰java高併發程序之並行程序調試

準備試驗樣本

實現樣本

/**
 * 兩個線程都過了數組大小檢查,先後插入數據時 引起 out of bound
 * @author Geym
 *
 */
public class UnsafeArrayList {
    static ArrayList al=new ArrayList();
    static class AddTask implements Runnable{
        @Override
        public void run() {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {}
            for(int i=0;i<1000000;i++)
                al.add(new Object());
        }
    }
    public static void main(String[] args) throws InterruptedException {
        Thread t1=new Thread(new AddTask(),"t1");
        Thread t2=new Thread(new AddTask(),"t2");
        t1.start();
        t2.start();
        Thread t3=new Thread(new Runnable(){
            @Override
            public void run() {
                while(true){
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {}
                }
            }
        },"t3");
        t3.start();
    }
}
ArrayList在多線程訪問情況下會出現異常`java.lang.ArrayIndexOutOfBoundsException: 11`

正式起航

ArrayList內部add()內部設置斷點.
clipboard.png

debug模式啓動,進入斷點,顯示完整堆棧,但顯示的是主線程的堆棧信息

clipboard.png

設置斷點屬性,使得只讓t1和t2線程進入斷點

clipboard.png

clipboard.png

掛起整個虛擬機

clipboard.png
掛起虛擬機而不是掛起線程

調試進入ArrayList內部

ArrayList的工作方式:
Arraylist內部初始化爲10個數組空間,當數組空間消耗完畢後,arraylist就會自動擴容.在每次add()函數時,系統總要事先檢查下內部空間是否滿足所需的大小.
多線程情況下,當arraylist容量快用完時,兩個線程同時進入add()函數,並同時認爲不需要擴容,且各自寫入自己的數據,那麼很可能有一個線程會將數據寫到邊界外,從而產生ArrayIndexOutOfBoundsException.

設置斷點,模擬到達線程擴容臨界點9:
clipboard.png

t1和t2線程均進入方法:

clipboard.png

t1線程執行到下一步,切換t2線程:

clipboard.png

t2線程執行到下一步,切換回t1線程進行添加元素:

clipboard.png

clipboard.png

t2線程拋出異常,ArrayIndexOutOfBoundsException:

clipboard.png

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章