概要介紹
首先說一下什么是線程不安全:線程安全就是多線程訪問時,采用了加鎖機制,當一個線程訪問該類的某個數據時,進行保護,其他線程不能進行訪問直到該線程讀取完,其他線程才可使用。不會出現數據不一致或者數據污染。線程不安全就是不提供數據訪問保護,有可能出現多個線程先后更改數據造成所得到的數據是臟數據。 如圖,List接口下面有兩個實現,一個是ArrayList,另外一個是vector。 從源碼的角度來看,因為Vector的方法前加了,synchronized 關鍵字,也就是同步的意思,sun公司希望Vector是線程安全的,而希望arraylist是高效的,缺點就是另外的優點。 說下原理(百度的,很好理解): 一個 ArrayList ,在添加一個元素的時候,它可能會有兩步來完成:
1. 在 Items[Size] 的位置存放此元素;
2. 增大 Size 的值。
在單線程運行的情況下,如果 Size = 0,添加一個元素后,此元素在位置 0,而且 Size=1;
而如果是在多線程情況下,比如有兩個線程,線程 A 先將元素存放在位置 0。但是此時 CPU 調度線程A暫停,線程 B 得到運行的機會。線程B也向此 ArrayList 添加元素,因為此時 Size 仍然等於 0 (注意哦,我們假設的是添加一個元素是要兩個步驟哦,而線程A僅僅完成了步驟1),所以線程B也將元素存放在位置0。然后線程A和線程B都繼續運行,都增加 Size 的值。
那好,現在我們來看看 ArrayList 的情況,元素實際上只有一個,存放在位置 0,而 Size 卻等於 2。這就是“線程不安全”了。
示例程序:
package test; import java.util.ArrayList; import java.util.List; public class ArrayListInThread implements Runnable { List<String> list1 = new ArrayList<String>();// not thread safe // List<String> list1 = Collections.synchronizedList(new ArrayList<String>());// thread safe public void run() { try { Thread.sleep((int)(Math.random() * 2)); } catch (InterruptedException e) { e.printStackTrace(); } list1.add(Thread.currentThread().getName()); } public static void main(String[] args) throws InterruptedException { ThreadGroup group = new ThreadGroup("mygroup"); ArrayListInThread t = new ArrayListInThread(); for (int i = 0; i < 10000; i++) { Thread th = new Thread(group, t, String.valueOf(i)); th.start(); } while (group.activeCount() > 0) { Thread.sleep(10); } System.out.println(); System.out.println(t.list1.size()); // it should be 10000 if thread safe collection is used. } }
- 頂
- 4
- 踩
- 1