線程安全,在java的多并發編程中是重要概念,意思是,多個線程同時操作一個對象,在各種不同情況下,都不會造成不同的后果。
一個經典問題,Vector到底是不是線程安全的?
很多人都會回答,是,vector是線程安全的。
誠然,不止是很多IT教材上是這么寫的,就連JDK的作者寫的注釋也是這么說的。如下圖(圖為 JDK中Vector的源代碼):注釋中,紅框標記的部分寫著:如果你不需要線程安全的實現類,那就推薦你用ArrayList,而不是Vector。言外之意,就是說,Vector是線程安全的。
自己看了源碼,發現,確實很多方法都有同步關鍵字synchronized,從而保證所有的對外接口都會以 Vector對象為鎖,即,在vector內部,所有的方法都不會被多線程訪問。
但是,單個方法的原子性(注:原子性,程序的原子性即不會被線程調度機制打斷),并不能保證復合操作也具有原子性。
(你問 為什么復合操作不能保證原子性? 參見大神的帖子:https://blog.csdn.net/xdonx/article/details/9465489 ,我沒太多時間研究細節,所以就只好剽竊大佬的結論了╮( ̄▽ ̄")╭)
所以,這個問題的正確回答應該是:
雖然源代碼注釋里面說這個是線程安全的,因為確實很多方法都加上了同步關鍵字synchronized,但是對于符合操作而言,只是同步方法并沒有解決線程安全的問題。
要真正達成線程安全,還需要以vector對象為鎖,來進行操作。
所以,如果是這樣的話,那么用vector和ArrayList就沒有區別了,所以,不推薦使用vector。
所以說,就算是JDK,也會有坑,畢竟坑坑更健康,有坑才能引導我們思考,畢竟做程序是理科工作,要有懷疑精神。
其實,具體為什么復合操作不具有原子性,我也沒有太深究,可能要從Vector代碼里面找根據,有空再探究。