我學習線程和整個這個片段這裏走來:爲什麼異步線程不能同時修改ArrayList?
我們創建並啓動兩個相同java.lang.Thread
S和讓他們不斷地修改0而不做任何有關這是非線程安全的,因爲我們要做的僅僅是研究。
這兩個線程只是同一類NoteThread
的實例。在run()
方法有兩種操作:
add(item)
從列表中選擇列表remove(0)
。
這兩個操作在1000次迭代中執行。
public class Solution {
public static void main(String[] args) {
new NoteThread().start();
new NoteThread().start();
}
public static class Note {
public static final List<String> notes = new ArrayList<String>();
public static void addNote(String note) {
notes.add(0, note);
}
public static void removeNote(String threadName) {
String note = notes.remove(0);
if (note == null) {
System.out.println("Another thread has already deleted the note");
} else if (!note.startsWith(threadName)) {
System.out.println("Thread [" + threadName + "] has deleted [" + note + "]");
}
}
}
public static class NoteThread extends Thread{
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
Note.addNote(getName() + "-Note" + i);
Note.removeNote(getName());
}
}
}
}
有時,它可以拋出IndexOutOfBoundsException: Index: 0, Size: -1
當列表是空的,我不明白怎麼說都可以。
輸出的一個例子:
Thread [Thread-1] has deleted [Thread-0-Note597] Another thread has already deleted the note Thread [Thread-0] has deleted [Thread-1-Note558] Another thread has already deleted the note Thread [Thread-1] has deleted [Thread-0-Note635] Another thread has already deleted the note Thread [Thread-0] has deleted [Thread-1-Note580]
我們可以100%肯定,認爲項目的創作總是發生它是缺失一個相同的線程之前,所以我認爲這是不可能遇到一個當一個線程想要刪除一個項目但沒有找到一個項目的情況。
UPDATE:Sergey Rybalkin已經非常清楚地解釋一個綱領性的執行順序的概念(這是我原來的問題沒有提及,但意思也無妨),最重要的是,他已經回答了這個問題:
如果
Thread 1
增加了一些內容,Thread 2
在某些情況下不會看到 中的更改。
在Java中,我們修改的每個對象實際上在每個線程中都有一個緩存副本,可以與它一起工作。因爲這個例子沒有對線程安全做任何事情,我們修改的數組也被緩存到每個線程。現在,既然如此,存在這樣的可能性:
注意,這只是我的理解,我不是專家
Thread 1
複製到陣列的緩存。Thread 2
將數組複製到其緩存中。Thread 1
將項目添加到其緩存陣列。Thread 2
將項目添加到其緩存陣列。Thread 1
從其緩存陣列中刪除項目。將其緩存的數組刷新到實際的數組中。JVM
傳播更改並將實際數組上載到該對象的所有用戶 - 到Thread 2
。所以,第二個線程現在擁有當前爲空的數組的更新版本。Thread 2
從其緩存陣列中刪除項目。- 異常:列表已經爲空:
IndexOutOfBoundsException: Index: 0,
Size: -1
p.s.我知道你不應該'延長線程' – Sam
你想同步嗎?因爲兩個線程都訪問相同的資源,即註釋 –
在同一個列表的併發修改之後,你期望什麼?嘗試閱讀一些理論之前盲目運行片段。您需要將您的訪問權限同步到此列表中,以避免不可預知的行爲 – Dimezis