多线程:Vector是线程安全的吗
線程安全,在java的多并發編程中是重要概念,意思是,多個線程同時操作一個對象,在各種不同情況下,都不會造成不同的后果。
一個經典問題,Vector到底是不是線程安全的?
?
很多人都會回答,是,vector是線程安全的。
誠然,不止是很多IT教材上是這么寫的,就連JDK的作者寫的注釋也是這么說的。如下圖(圖為 JDK中Vector的源代碼):注釋中,紅框標記的部分寫著:如果你不需要線程安全的實現類,那就推薦你用ArrayList,而不是Vector。言外之意,就是說,Vector是線程安全的。
自己看了源碼,發現,確實很多方法都有同步關鍵字synchronized,從而保證所有的對外接口都會以 Vector對象為鎖,即,在vector內部,所有的方法都不會被多線程訪問。
但是,單個方法的原子性(注:原子性,程序的原子性即不會被線程調度機制打斷),并不能保證復合操作也具有原子性。
所以,這個問題的正確回答應該是:
雖然源代碼注釋里面說這個是線程安全的,因為確實很多方法都加上了同步關鍵字synchronized,但是對于復合操作而言,只是同步方法但并沒有解決線程安全的問題。因為在兩個原子操作之間存在間隙,在多線程環境中,完全有可能被其他線程獲得 vector的 lock 并改變其狀態。要真正達成線程安全,還需要以vector對象為鎖,來進行操作。所以,如果是這樣的話,那么用vector和ArrayList就沒有區別了,所以,不推薦使用vector。
舉個栗子:
if (!vector.contains(element))?vector.add(element);?... }
這是經典的?put-if-absent?情況,盡管 contains, add 方法都正確地同步了,但作為 vector?之外的使用環境,仍然存在??race condition: 因為雖然條件判斷?if (!vector.contains(element))與方法調用?vector.add(element);??都是原子性的操作 (atomic),但在 if 條件判斷為真后,那個用來訪問vector.contains 方法的鎖已經釋放,在即將的 vector.add?方法調用 之間有間隙,在多線程環境中,完全有可能被其他線程獲得 vector的 lock 并改變其狀態, 此時當前線程的vector.add(element);??正在等待(只不過我們不知道而已)。只有當其他線程釋放了 vector 的 lock 后,vector.add(element);?繼續,但此時它已經基于一個錯誤的假設了。
單個的方法 synchronized 了并不代表組合(compound)的方法調用具有原子性,使 compound actions? 成為線程安全的可能解決辦法之一還是離不開intrinsic lock?(這個鎖應該是 vector 的,但由 client 維護):
?
總結
以上是生活随笔為你收集整理的多线程:Vector是线程安全的吗的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 框架:springboot组合sprin
- 下一篇: 多线程:interrupted、isin