這幾天看到論壇首頁有一個挺熱的帖子Vector和ArrayList的本質區別到底是什么?,正好是自己正在學習的內容,所以也在這發個帖子,獻獻丑,如有寫得不正確的,還希望各位同學斧正
帖子討論的是面試中常見的Vector,ArrayList以及與其類似的“線程安全類”的問題
里面有幾個關鍵點:
1.線程安全的定義
2.像Vector,HashTable這樣幾乎在所有方法都添加上"synchronized"能否達到線程安全的效果?(細心點的同學可能還會發現Collections.synchronizedSortedMap,Collections.synchronizedList等是用了同樣的手段)
3.Vector到底有沒有性能上的問題呢?
天朝人寫的東西都沒太大的說服力,所以盡量還是引用老外"Doug Lea"的經典《Java Concurrency in Practice》做為論述的依據
關于問題1的解釋是這樣的
A class is thread-safe if it behaves correctly when accessed from multiple threads, regardless of the scheduling or interleaving of the execution of those threads by the runtime environment, and with no additional synchronization or other coordination on the part of the calling code.
關于問題2呢,首先,需要知道synchronized一個方法到底是一個怎樣的操作
解釋是這樣的:
Java provides a built-in locking mechanism for enforcing atomicity: the synchronized block. (There is also another critical aspect to locking and other synchronization mechanismsvisibilitywhich is covered in Chapter 3.) A synchronized block has two parts: a reference to an object that will serve as the lock, and a block of code to be guarded by that lock. A synchronized method is a shorthand for a synchronized block that spans an entire method body, and whose lock is the object on which the method is being invoked. (Static synchronized methods use the Class object for the lock.)
Every Java object can implicitly act as a lock for purposes of synchronization; these built-in locks are called intrinsic locks or monitor locks. The lock is automatically acquired by the executing thread before entering a synchronized block and automatically released when control exits the synchronized block, whether by the normal control path or by throwing an exception out of the block. The only way to acquire an intrinsic lock is to enter a synchronized block or method guarded by that lock.
也就是說,如果在每個方法前都加上了"synchronized",會起到這樣的效果:當一個線程調用任一個該類的方法時,都要先去獲取該對象的固有鎖"intrinsic lock",然后才進行操作,如果當一個線程正在執行某個方法時,另一個線程也請求進入,那就需要等待前者執行完才能獲得鎖,然后繼續執行
細心的tx想必看出來了,這樣會造成嚴重的效率問題,比如多個線程同時執行get操作,它們根本是不可能相互影響的,但卻也需要分別獲得鎖才能繼續執行,單憑這一點就可以為問題3做一個結論了
然后再說說到底能不能達到線程安全的效果呢?
答案也是否定的
看一個例子:
顯然,這個操作違背了上文所說的"A class is thread-safe if it behaves correctly when accessed from multiple threads"的效果
然后繼續看問題3
The performance cost of synchronization comes from several sources. The visibility guarantees provided by synchronized and volatile may entail using special instructions called memory barriers that can flush or invalidate caches, flush hardware write buffers, and stall execution pipelines. Memory barriers may also have indirect performance consequences because they inhibit other compiler optimizations; most operations cannot be reordered with memory barriers.
從這段話可以看出,synchronized是會影響jvm的優化的,所以問題3的答案也很明確了:
會有性能上的問題
不過對于一些老公司,看到通篇的使用HashTable和Vector,也不必太擔憂了
因為:
Modern JVMs can reduce the cost of incidental synchronization by optimizing away locking that can be proven never to contend. If a lock object is accessible only to the current thread, the JVM is permitted to optimize away a lock acquisition because there is no way another thread could synchronize on the same lock.
在這,也順便為這本經典書打打廣告,反正小弟看了是受益匪淺的,有興趣的tx可以下載看看
已有 12 人發表留言,猛擊->>這里<<-參與討論
ItEye推薦
帖子討論的是面試中常見的Vector,ArrayList以及與其類似的“線程安全類”的問題
里面有幾個關鍵點:
1.線程安全的定義
2.像Vector,HashTable這樣幾乎在所有方法都添加上"synchronized"能否達到線程安全的效果?(細心點的同學可能還會發現Collections.synchronizedSortedMap,Collections.synchronizedList等是用了同樣的手段)
3.Vector到底有沒有性能上的問題呢?
天朝人寫的東西都沒太大的說服力,所以盡量還是引用老外"Doug Lea"的經典《Java Concurrency in Practice》做為論述的依據
關于問題1的解釋是這樣的
A class is thread-safe if it behaves correctly when accessed from multiple threads, regardless of the scheduling or interleaving of the execution of those threads by the runtime environment, and with no additional synchronization or other coordination on the part of the calling code.
關于問題2呢,首先,需要知道synchronized一個方法到底是一個怎樣的操作
解釋是這樣的:
Java provides a built-in locking mechanism for enforcing atomicity: the synchronized block. (There is also another critical aspect to locking and other synchronization mechanismsvisibilitywhich is covered in Chapter 3.) A synchronized block has two parts: a reference to an object that will serve as the lock, and a block of code to be guarded by that lock. A synchronized method is a shorthand for a synchronized block that spans an entire method body, and whose lock is the object on which the method is being invoked. (Static synchronized methods use the Class object for the lock.)
Every Java object can implicitly act as a lock for purposes of synchronization; these built-in locks are called intrinsic locks or monitor locks. The lock is automatically acquired by the executing thread before entering a synchronized block and automatically released when control exits the synchronized block, whether by the normal control path or by throwing an exception out of the block. The only way to acquire an intrinsic lock is to enter a synchronized block or method guarded by that lock.
也就是說,如果在每個方法前都加上了"synchronized",會起到這樣的效果:當一個線程調用任一個該類的方法時,都要先去獲取該對象的固有鎖"intrinsic lock",然后才進行操作,如果當一個線程正在執行某個方法時,另一個線程也請求進入,那就需要等待前者執行完才能獲得鎖,然后繼續執行
細心的tx想必看出來了,這樣會造成嚴重的效率問題,比如多個線程同時執行get操作,它們根本是不可能相互影響的,但卻也需要分別獲得鎖才能繼續執行,單憑這一點就可以為問題3做一個結論了
然后再說說到底能不能達到線程安全的效果呢?
答案也是否定的
看一個例子:
if (!vector.contains(element)) vector.add(element);
顯然,這個操作違背了上文所說的"A class is thread-safe if it behaves correctly when accessed from multiple threads"的效果
然后繼續看問題3
The performance cost of synchronization comes from several sources. The visibility guarantees provided by synchronized and volatile may entail using special instructions called memory barriers that can flush or invalidate caches, flush hardware write buffers, and stall execution pipelines. Memory barriers may also have indirect performance consequences because they inhibit other compiler optimizations; most operations cannot be reordered with memory barriers.
從這段話可以看出,synchronized是會影響jvm的優化的,所以問題3的答案也很明確了:
會有性能上的問題
不過對于一些老公司,看到通篇的使用HashTable和Vector,也不必太擔憂了
因為:
Modern JVMs can reduce the cost of incidental synchronization by optimizing away locking that can be proven never to contend. If a lock object is accessible only to the current thread, the JVM is permitted to optimize away a lock acquisition because there is no way another thread could synchronize on the same lock.
在這,也順便為這本經典書打打廣告,反正小弟看了是受益匪淺的,有興趣的tx可以下載看看
-
本文附件下載:
- Addison.Wesley.Java.Concurrency.in.Pract....rar (1.2 MB)
已有 12 人發表留言,猛擊->>這里<<-參與討論
ItEye推薦